From 80215ea1818874bcd3661259df6f2d3279cc59f2 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 23 May 2018 15:36:35 -0700 Subject: LibMem + TestLibMem + LibAssetProxyDecoder + DummyERC721Receiver --- packages/contracts/compiler.json | 2 + .../current/protocol/AssetProxy/ERC20Proxy.sol | 24 +-- .../current/protocol/AssetProxy/ERC721Proxy.sol | 28 ++- .../DummyERC721Receiver/DummyERC721Receiver.sol | 62 ++++++ .../current/test/TestLibMem/TestLibMem.sol | 238 +++++++++++++++++++++ .../LibAssetProxyDecoder/LibAssetProxyDecoder.sol | 74 +++++++ .../contracts/current/utils/LibBytes/LibBytes.sol | 76 ++++++- .../src/contracts/current/utils/LibMem/LibMem.sol | 104 +++++++++ 8 files changed, 581 insertions(+), 27 deletions(-) create mode 100644 packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol create mode 100644 packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol create mode 100644 packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol create mode 100644 packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol diff --git a/packages/contracts/compiler.json b/packages/contracts/compiler.json index 48ba4ffcd..a11f2a2c0 100644 --- a/packages/contracts/compiler.json +++ b/packages/contracts/compiler.json @@ -22,6 +22,7 @@ "AssetProxyOwner", "DummyERC20Token", "DummyERC721Token", + "DummyERC721Receiver", "ERC20Proxy", "ERC721Proxy", "Exchange", @@ -30,6 +31,7 @@ "MultiSigWalletWithTimeLock", "TestAssetProxyDispatcher", "TestLibBytes", + "TestLibMem", "TestLibs", "TestSignatureValidator", "TokenRegistry", diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 2c321e134..017f94b1a 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -20,12 +20,14 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; +import "../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol"; import "./MixinAssetProxy.sol"; import "./MixinAuthorizable.sol"; import "../../tokens/ERC20Token/IERC20Token.sol"; contract ERC20Proxy is LibBytes, + LibAssetProxyDecoder, MixinAssetProxy, MixinAuthorizable { @@ -34,34 +36,32 @@ contract ERC20Proxy is uint8 constant PROXY_ID = 1; /// @dev Internal version of `transferFrom`. - /// @param assetMetadata Encoded byte array. + /// @param proxyData Encoded byte array. /// @param from Address to transfer asset from. /// @param to Address to transfer asset to. /// @param amount Amount of asset to transfer. function transferFromInternal( - bytes memory assetMetadata, + bytes memory proxyData, address from, address to, uint256 amount ) internal { + // Decode proxy data. + ( + uint8 proxyId, + address token + ) = decodeERC20Data(proxyData); + // Data must be intended for this proxy. uint256 length = assetMetadata.length; require( - length == 21, - LENGTH_21_REQUIRED - ); - // TODO: Is this too inflexible in the future? - require( - uint8(assetMetadata[length - 1]) == PROXY_ID, - ASSET_PROXY_ID_MISMATCH + proxyId == PROXY_ID, + PROXY_ID_MISMATCH ); - // Decode metadata. - address token = readAddress(assetMetadata, 0); - // Transfer tokens. bool success = IERC20Token(token).transferFrom(from, to, amount); require( diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 07e01c774..f35e48eee 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -20,12 +20,14 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; +import "../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol"; import "./MixinAssetProxy.sol"; import "./MixinAuthorizable.sol"; import "../../tokens/ERC721Token/ERC721Token.sol"; contract ERC721Proxy is LibBytes, + LibAssetProxyDecoder, MixinAssetProxy, MixinAuthorizable { @@ -33,19 +35,29 @@ contract ERC721Proxy is // Id of this proxy. uint8 constant PROXY_ID = 2; + string constant PROXY_ID_MISMATCH = "Proxy id in metadata does not match this proxy id."; + /// @dev Internal version of `transferFrom`. - /// @param assetMetadata Encoded byte array. + /// @param proxyData Encoded byte array. /// @param from Address to transfer asset from. /// @param to Address to transfer asset to. /// @param amount Amount of asset to transfer. function transferFromInternal( - bytes memory assetMetadata, + bytes memory proxyData, address from, address to, uint256 amount ) internal { + // Decode proxy data. + ( + uint8 proxyId, + address token, + uint256 tokenId, + bytes memory data + ) = decodeERC721Data(proxyData); + // Data must be intended for this proxy. uint256 length = assetMetadata.length; @@ -56,8 +68,8 @@ contract ERC721Proxy is // TODO: Is this too inflexible in the future? require( - uint8(assetMetadata[length - 1]) == PROXY_ID, - ASSET_PROXY_ID_MISMATCH + proxyId == PROXY_ID, + PROXY_ID_MISMATCH ); // There exists only 1 of each token. @@ -66,15 +78,9 @@ contract ERC721Proxy is INVALID_AMOUNT ); - // Decode metadata - address token = readAddress(assetMetadata, 0); - uint256 tokenId = readUint256(assetMetadata, 20); - // Transfer token. // Either succeeds or throws. - // @TODO: Call safeTransferFrom if there is additional - // data stored in `assetMetadata`. - ERC721Token(token).transferFrom(from, to, tokenId); + ERC721Token(token).safeTransferFrom(from, to, tokenId, data); } /// @dev Gets the proxy id associated with the proxy address. diff --git a/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol b/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol new file mode 100644 index 000000000..1596f3357 --- /dev/null +++ b/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol @@ -0,0 +1,62 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 Smart Contract Solutions, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +pragma solidity ^0.4.24; + +import "../../tokens/ERC721Token/IERC721Receiver.sol"; + +contract DummyERC721Receiver is + IERC721Receiver +{ + + event TokenReceived( + address from, + uint256 tokenId, + bytes data + ); + + /** + * @notice Handle the receipt of an NFT + * @dev The ERC721 smart contract calls this function on the recipient + * after a `safetransfer`. This function MAY throw to revert and reject the + * transfer. This function MUST use 50,000 gas or less. Return of other + * than the magic value MUST result in the transaction being reverted. + * Note: the contract address is always the message sender. + * @param _from The sending address + * @param _tokenId The NFT identifier which is being transfered + * @param _data Additional data with no specified format + * @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))` + */ + function onERC721Received( + address _from, + uint256 _tokenId, + bytes _data) + public + returns (bytes4) + { + emit TokenReceived(_from, _tokenId, _data); + return ERC721_RECEIVED; + } +} diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol new file mode 100644 index 000000000..4cf62bf3a --- /dev/null +++ b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol @@ -0,0 +1,238 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; + +import "../../utils/LibMem/LibMem.sol"; +import "../../utils/LibBytes/LibBytes.sol"; + +contract TestLibMem is + LibMem, + LibBytes +{ + + function test1() + public + pure + { + // Length of array & length to copy + uint256 length = 0; + + // Create source array + bytes memory sourceArray = new bytes(length); + + // Create dest array with same contents as source array + bytes memory destArray = new bytes(length); + memcpy( + getMemAddress(destArray) + 32, // skip copying array length + getMemAddress(sourceArray) + 32, // skip copying array length + length + ); + + // Verify contents of source & dest arrays match + require( + areBytesEqual(sourceArray, destArray), + "Test #1 failed. Array contents are not the same." + ); + } + + function test2() + public + pure + { + // Length of array & length to copy + uint256 length = 1; + + // Create source array + bytes memory sourceArray = new bytes(length); + sourceArray[0] = byte(1); + + // Create dest array with same contents as source array + bytes memory destArray = new bytes(length); + memcpy( + getMemAddress(destArray) + 32, // skip copying array length + getMemAddress(sourceArray) + 32, // skip copying array length + length + ); + + // Verify contents of source & dest arrays match + require( + areBytesEqual(sourceArray, destArray), + "Test #2 failed. Array contents are not the same." + ); + } + + function test3() + public + pure + { + // Length of array & length to copy + uint256 length = 11; + + // Create source array + bytes memory sourceArray = new bytes(length); + for(uint256 i = 0; i < length; ++i) { + sourceArray[i] = byte((i % 0xF) + 1); // [1..f] + } + + // Create dest array with same contents as source array + bytes memory destArray = new bytes(length); + memcpy( + getMemAddress(destArray) + 32, // skip copying array length + getMemAddress(sourceArray) + 32, // skip copying array length + length + ); + + // Verify contents of source & dest arrays match + require( + areBytesEqual(sourceArray, destArray), + "Test #3 failed. Array contents are not the same." + ); + } + + function test4() + public + pure + { + // Length of array & length to copy + uint256 length = 32; + + // Create source array + bytes memory sourceArray = new bytes(length); + for(uint256 i = 0; i < length; ++i) { + sourceArray[i] = byte((i % 0xF) + 1); // [1..f] + } + + // Create dest array with same contents as source array + bytes memory destArray = new bytes(length); + memcpy( + getMemAddress(destArray) + 32, // skip copying array length + getMemAddress(sourceArray) + 32, // skip copying array length + length + ); + + // Verify contents of source & dest arrays match + require( + areBytesEqual(sourceArray, destArray), + "Test #4 failed. Array contents are not the same." + ); + } + + function test5() + public + pure + { + // Length of array & length to copy + uint256 length = 72; + + // Create source array + bytes memory sourceArray = new bytes(length); + for(uint256 i = 0; i < length; ++i) { + sourceArray[i] = byte((i % 0xF) + 1); // [1..f] + } + + // Create dest array with same contents as source array + bytes memory destArray = new bytes(length); + memcpy( + getMemAddress(destArray) + 32, // skip copying array length + getMemAddress(sourceArray) + 32, // skip copying array length + length + ); + + // Verify contents of source & dest arrays match + require( + areBytesEqual(sourceArray, destArray), + "Test #5 failed. Array contents are not the same." + ); + } + + + function test6() + public + pure + { + // Length of arrays + uint256 length1 = 72; + uint256 length2 = 100; + + // The full source array is used for comparisons at the end + bytes memory fullSourceArray = new bytes(length1 + length2); + + // First source array + bytes memory sourceArray1 = new bytes(length1); + for(uint256 i = 0; i < length1; ++i) { + sourceArray1[i] = byte((i % 0xF) + 1); // [1..f] + fullSourceArray[i] = byte((i % 0xF) + 1); // [1..f] + } + + // Second source array + bytes memory sourceArray2 = new bytes(length2); + for(uint256 j = 0; i < length2; ++i) { + sourceArray2[j] = byte((j % 0xF) + 1); // [1..f] + fullSourceArray[length1+j] = byte((j % 0xF) + 1); // [1..f] + } + + // Create dest array with same contents as source arrays + bytes memory destArray = new bytes(length1 + length2); + memcpy( + getMemAddress(destArray) + 32, // skip copying array length + getMemAddress(sourceArray1) + 32, // skip copying array length + length1 + ); + memcpy( + getMemAddress(destArray) + 32 + length1, // skip copying array length + sourceArray1 bytes + getMemAddress(sourceArray2) + 32, // skip copying array length + length2 + ); + + // Verify contents of source & dest arrays match + require( + areBytesEqual(fullSourceArray, destArray), + "Test #6 failed. Array contents are not the same." + ); + } + + function test7() + public + pure + { + // Length of array & length to copy + uint256 length = 72; + + // Create source array + bytes memory sourceArray = new bytes(length); + for(uint256 i = 0; i < length; ++i) { + sourceArray[i] = byte((i % 0xF) + 1); // [1..f] + } + + // Create dest array with same contents as source array + bytes memory destArray = new bytes(length); + memcpy( + getMemAddress(destArray) + 32, // skip copying array length + getMemAddress(sourceArray) + 32, // skip copying array length + length - 8 // Copy all but last byte. + ); + + // Verify contents of source & dest arrays match + // We expect this to fail + require( + areBytesEqual(sourceArray, destArray), + "Test #7 failed. Array contents are not the same." + ); + } +} diff --git a/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol b/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol new file mode 100644 index 000000000..ba53f2769 --- /dev/null +++ b/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol @@ -0,0 +1,74 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; +pragma experimental ABIEncoderV2; + +import "../LibBytes/LibBytes.sol"; + +contract LibAssetProxyDecoder is + LibBytes +{ + + string constant INVALID_ERC20_METADATA_LENGTH = "Metadata must have a length of 21."; + string constant INVALID_ERC721_METADATA_LENGTH = "Metadata must have a length of at least 53."; + + /// @dev Decodes ERC721 Asset Proxy data + function decodeERC20Data(bytes memory proxyData) + internal + pure + returns ( + uint8 proxyId, + address token + ) + { + require( + proxyData.length == 21, + INVALID_ERC20_METADATA_LENGTH + ); + proxyId = uint8(proxyData[0]); + token = readAddress(proxyData, 1); + + return (proxyId, token); + } + + /// @dev Decodes ERC721 Asset Proxy data + function decodeERC721Data(bytes memory proxyData) + internal + pure + returns ( + uint8 proxyId, + address token, + uint256 tokenId, + bytes memory data + ) + { + require( + proxyData.length >= 53, + INVALID_ERC721_METADATA_LENGTH + ); + proxyId = uint8(proxyData[0]); + token = readAddress(proxyData, 1); + tokenId = readUint256(proxyData, 21); + if (proxyData.length > 53) { + data = readBytes(proxyData, 53); + } + + return (proxyId, token, tokenId, data); + } +} diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index df2221c93..fb8359462 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -18,7 +18,11 @@ pragma solidity ^0.4.24; -contract LibBytes { +import "../LibMem/LibMem.sol"; + +contract LibBytes is + LibMem +{ // Revert reasons string constant GT_ZERO_LENGTH_REQUIRED = "Length must be greater than 0."; @@ -42,7 +46,7 @@ contract LibBytes { // Store last byte. result = b[b.length - 1]; - + assembly { // Decrement length of byte array. let newLen := sub(mload(b), 1) @@ -125,7 +129,7 @@ contract LibBytes { require( b.length >= index + 20, // 20 is length of address GTE_20_LENGTH_REQUIRED - ); + ); // Add offset to index: // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index) @@ -157,7 +161,7 @@ contract LibBytes { require( b.length >= index + 20, // 20 is length of address GTE_20_LENGTH_REQUIRED - ); + ); // Add offset to index: // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index) @@ -264,6 +268,7 @@ contract LibBytes { writeBytes32(b, index, bytes32(input)); } +======= /// @dev Reads the first 4 bytes from a byte array of arbitrary length. /// @param b Byte array to read first 4 bytes from. /// @return First 4 bytes of data. @@ -281,4 +286,67 @@ contract LibBytes { } return result; } + + /// @dev Reads a uint256 value from a position in a byte array. + /// @param b Byte array containing a uint256 value. + /// @param index Index in byte array of uint256 value. + /// @return uint256 value from byte array. + function readBytes( + bytes memory b, + uint256 index + ) + internal + pure + returns (bytes memory result) + { + // Read length of nested bytes + require( + b.length >= index + 32, + GTE_32_LENGTH_REQUIRED + ); + uint256 nestedBytesLength = readUint256(b, index); + + // Assert length of is valid, given + // length of nested bytes + require( + b.length >= index + 32 + nestedBytesLength, + GTE_32_LENGTH_REQUIRED + ); + + // Allocate memory and copy value to result + result = new bytes(nestedBytesLength); + memcpy( + getMemAddress(result) + 32, // +32 skips array length + getMemAddress(b) + index + 32, // +32 skips array length + nestedBytesLength + ); + + return result; + } + + /// @dev Writes a uint256 into a specific position in a byte array. + /// @param b Byte array to insert into. + /// @param index Index in byte array of . + /// @param input uint256 to put into byte array. + function writeBytes( + bytes memory b, + uint256 index, + bytes memory input + ) + internal + pure + { + // Read length of nested bytes + require( + b.length >= index + 32 /* 32 bytes to store length */ + input.length, + GTE_32_LENGTH_REQUIRED + ); + + // Copy into + memcpy( + getMemAddress(b) + index, + getMemAddress(input), + input.length + 32 /* 32 bytes to store length */ + ); + } } diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol new file mode 100644 index 000000000..b07a5da54 --- /dev/null +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -0,0 +1,104 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; + +contract LibMem { + + function getMemAddress(bytes memory input) + internal + pure + returns (uint256 address_) + { + assembly { + address_ := input + } + return address_; + } + + /// @dev Writes a uint256 into a specific position in a byte array. + /// @param dest memory adress to copy bytes to + function memcpy( + uint256 dest, + uint256 source, + uint256 length + ) + internal + pure + { + // Base cases + if(length == 0) return; + if(source == dest) return; + + // Copy bytes from source to dest + assembly { + // Compute number of complete words to copy + remaining bytes + let lenFullWords := div(add(length, 0x1F), 0x20) + let remainder := mod(length, 0x20) + if gt(remainder, 0) { + lenFullWords := sub(lenFullWords, 1) + } + + // Copy full words from source to dest + let offset := 0 + let maxOffset := mul(0x20, lenFullWords) + for {offset := 0} lt(offset, maxOffset) {offset := add(offset, 0x20)} { + mstore(add(dest, offset), mload(add(source, offset))) + } + + // Copy remaining bytes + if gt(remainder, 0) { + // Read a full word from source, containing X bytes to copy to dest. + // We only want to keep the X bytes, zeroing out the remaining bytes. + // We accomplish this by a right shift followed by a left shift. + // Example: + // Suppose a word of 8 bits has all 1's: [11111111] + // Let X = 7 (we want to copy the first 7 bits) + // Apply a right shift of 1: [01111111] + // Apply a left shift of 1: [11111110] + let sourceShiftFactor := exp(2, mul(8, sub(0x20, remainder))) + let sourceWord := mload(add(source, offset)) + let sourceBytes := mul(div(sourceWord, sourceShiftFactor), sourceShiftFactor) + + // Read a full word from dest, containing (32-X) bytes to retain. + // We need to zero out the remaining bytes to be overwritten by source, + // while retaining the (32-X) bytes we don't want to overwrite. + // We accomplish this by a left shift followed by a right shift. + // Example: + // Suppose a word of 8 bits has all 1's: [11111111] + // Let X = 7 (we want to free the first 7 bits, and retain the last bit) + // Apply a left shift of 1: [11111110] + // Apply a right shift of 1: [01111111] + let destShiftFactor := exp(2, mul(8, remainder)) + let destWord := mload(add(dest, offset)) + let destBytes := div(mul(destWord, destShiftFactor), destShiftFactor) + + // Combine the source and dest bytes. There should be no overlap: + // The source bytes run from [0..X-1] and the dest bytes from [X..31]. + // Example: + // Following the example from above, we have [11111110] + // from the source word and [01111111] from the dest word. + // Combine these words using to get [11111111]. + let combinedDestWord := or(sourceBytes, destBytes) + + // Store the combined word into dest + mstore(add(dest, offset), combinedDestWord) + } + } + } +} -- cgit v1.2.3 From 3d65341080177bdd436e7628a76e65774b947a38 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 24 May 2018 10:56:47 -0700 Subject: Tests for libMem --- packages/contracts/package.json | 2 +- .../current/test/TestLibMem/TestLibMem.sol | 23 +++----- packages/contracts/src/utils/artifacts.ts | 2 + packages/contracts/src/utils/types.ts | 1 + packages/contracts/test/libraries/lib_mem.ts | 68 ++++++++++++++++++++++ 5 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 packages/contracts/test/libraries/lib_mem.ts diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 99c507197..009fe87ec 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -30,7 +30,7 @@ "test:circleci": "yarn test" }, "config": { - "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" + "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" }, "repository": { "type": "git", diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol index 4cf62bf3a..0c6f8fbc9 100644 --- a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol +++ b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol @@ -27,8 +27,7 @@ contract TestLibMem is { function test1() - public - pure + external { // Length of array & length to copy uint256 length = 0; @@ -52,8 +51,7 @@ contract TestLibMem is } function test2() - public - pure + external { // Length of array & length to copy uint256 length = 1; @@ -78,8 +76,7 @@ contract TestLibMem is } function test3() - public - pure + external { // Length of array & length to copy uint256 length = 11; @@ -106,8 +103,7 @@ contract TestLibMem is } function test4() - public - pure + external { // Length of array & length to copy uint256 length = 32; @@ -134,8 +130,7 @@ contract TestLibMem is } function test5() - public - pure + external { // Length of array & length to copy uint256 length = 72; @@ -163,8 +158,7 @@ contract TestLibMem is function test6() - public - pure + external { // Length of arrays uint256 length1 = 72; @@ -208,8 +202,7 @@ contract TestLibMem is } function test7() - public - pure + external { // Length of array & length to copy uint256 length = 72; @@ -232,7 +225,7 @@ contract TestLibMem is // We expect this to fail require( areBytesEqual(sourceArray, destArray), - "Test #7 failed. Array contents are not the same." + "Test #7 failed. Array contents are not the same. This is expected." ); } } diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index 357c66a0a..1b47f1d41 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -11,6 +11,7 @@ import * as MultiSigWallet from '../artifacts/MultiSigWallet.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json'; import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json'; import * as TestLibBytes from '../artifacts/TestLibBytes.json'; +import * as TestLibMem from '../artifacts/TestLibMem.json'; import * as TestLibs from '../artifacts/TestLibs.json'; import * as TestSignatureValidator from '../artifacts/TestSignatureValidator.json'; import * as TokenRegistry from '../artifacts/TokenRegistry.json'; @@ -31,6 +32,7 @@ export const artifacts = { MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact, TestAssetProxyDispatcher: (TestAssetProxyDispatcher as any) as ContractArtifact, TestLibBytes: (TestLibBytes as any) as ContractArtifact, + TestLibMem: (TestLibMem as any) as ContractArtifact, TestLibs: (TestLibs as any) as ContractArtifact, TestSignatureValidator: (TestSignatureValidator as any) as ContractArtifact, TokenRegistry: (TokenRegistry as any) as ContractArtifact, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 491890fa1..cc6f00b95 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -91,6 +91,7 @@ export enum ContractName { EtherDelta = 'EtherDelta', Arbitrage = 'Arbitrage', TestAssetProxyDispatcher = 'TestAssetProxyDispatcher', + TestLibMem = 'TestLibMem', TestLibs = 'TestLibs', TestSignatureValidator = 'TestSignatureValidator', ERC20Proxy = 'ERC20Proxy', diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts new file mode 100644 index 000000000..c861484f3 --- /dev/null +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -0,0 +1,68 @@ +import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js'; +import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import BN = require('bn.js'); +import * as chai from 'chai'; +import ethUtil = require('ethereumjs-util'); +import * as Web3 from 'web3'; + +import { TestLibMemContract } from '../../src/contract_wrappers/generated/test_lib_mem'; +import { artifacts } from '../../src/utils/artifacts'; +import { chaiSetup } from '../../src/utils/chai_setup'; +import { constants } from '../../src/utils/constants'; +import { AssetProxyId } from '../../src/utils/types'; +import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe.only('LibMem', () => { + let owner: string; + let testLibMem: TestLibMemContract; + + before(async () => { + // Setup accounts & addresses + const accounts = await web3Wrapper.getAvailableAddressesAsync(); + owner = accounts[0]; + // Deploy TestLibMem + testLibMem = await TestLibMemContract.deployFrom0xArtifactAsync(artifacts.TestLibMem, provider, txDefaults); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + + describe('LibMem', () => { + it('should )', async () => { + await testLibMem.test1.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test2.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test3.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test4.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test5.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test6.sendTransactionAsync(); + }); + + it('should )', async () => { + return expect(testLibMem.test7.sendTransactionAsync()).to.be.rejectedWith(constants.REVERT); + }); + }); +}); -- cgit v1.2.3 From 9b82e2df58cfd7f4dc9954fa93167450919f457f Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 24 May 2018 12:29:45 -0700 Subject: Foundation for TestLibAssetProxyDecoder --- packages/contracts/compiler.json | 1 + packages/contracts/package.json | 2 +- .../TestLibAssetProxyDecoder.sol | 50 ++++++++++++ packages/contracts/src/utils/artifacts.ts | 2 + packages/contracts/src/utils/types.ts | 1 + packages/contracts/test/asset_proxy/decoder.ts | 72 ++++++++++++++++++ packages/contracts/test/libraries/lib_mem.ts | 2 +- .../artifacts/2.0.0/TestLibAssetProxyDecoder.json | 88 ++++++++++++++++++++++ 8 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol create mode 100644 packages/contracts/test/asset_proxy/decoder.ts create mode 100644 packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json diff --git a/packages/contracts/compiler.json b/packages/contracts/compiler.json index a11f2a2c0..639849cd7 100644 --- a/packages/contracts/compiler.json +++ b/packages/contracts/compiler.json @@ -29,6 +29,7 @@ "MixinAuthorizable", "MultiSigWallet", "MultiSigWalletWithTimeLock", + "TestLibAssetProxyDecoder", "TestAssetProxyDispatcher", "TestLibBytes", "TestLibMem", diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 009fe87ec..43c33e7d3 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -30,7 +30,7 @@ "test:circleci": "yarn test" }, "config": { - "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" + "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibAssetProxyDecoder|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" }, "repository": { "type": "git", diff --git a/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol b/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol new file mode 100644 index 000000000..ac7cd63ab --- /dev/null +++ b/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol @@ -0,0 +1,50 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; +pragma experimental ABIEncoderV2; + +import "../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol"; + +contract TestLibAssetProxyDecoder is + LibAssetProxyDecoder +{ + + /// @dev Decodes ERC721 Asset Proxy data + function publicDecodeERC20Data(bytes memory proxyData) + public + pure + returns (uint8, address) + { + return decodeERC20Data(proxyData); + } + + /// @dev Decodes ERC721 Asset Proxy data + function publicDecodeERC721Data(bytes memory proxyData) + internal + pure + returns ( + uint8, + address, + uint256, + bytes memory + ) + { + return decodeERC721Data(proxyData); + } +} diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index 1b47f1d41..44de43a95 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -10,6 +10,7 @@ import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json'; import * as MultiSigWallet from '../artifacts/MultiSigWallet.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json'; import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json'; +import * as TestLibAssetProxyDecoder from '../artifacts/TestLibAssetProxyDecoder.json'; import * as TestLibBytes from '../artifacts/TestLibBytes.json'; import * as TestLibMem from '../artifacts/TestLibMem.json'; import * as TestLibs from '../artifacts/TestLibs.json'; @@ -31,6 +32,7 @@ export const artifacts = { MultiSigWallet: (MultiSigWallet as any) as ContractArtifact, MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact, TestAssetProxyDispatcher: (TestAssetProxyDispatcher as any) as ContractArtifact, + TestLibAssetProxyDecoder: (TestLibAssetProxyDecoder as any) as ContractArtifact, TestLibBytes: (TestLibBytes as any) as ContractArtifact, TestLibMem: (TestLibMem as any) as ContractArtifact, TestLibs: (TestLibs as any) as ContractArtifact, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index cc6f00b95..70abb2643 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -90,6 +90,7 @@ export enum ContractName { AccountLevels = 'AccountLevels', EtherDelta = 'EtherDelta', Arbitrage = 'Arbitrage', + TestLibAssetProxyDecoder = 'TestLibAssetProxyDecoder', TestAssetProxyDispatcher = 'TestAssetProxyDispatcher', TestLibMem = 'TestLibMem', TestLibs = 'TestLibs', diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts new file mode 100644 index 000000000..74e7547d3 --- /dev/null +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -0,0 +1,72 @@ +import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js'; +import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import BN = require('bn.js'); +import * as chai from 'chai'; +import ethUtil = require('ethereumjs-util'); +import * as Web3 from 'web3'; + +import { TestLibAssetProxyDecoderContract } from '../../src/contract_wrappers/generated/test_lib_asset_proxy_decoder'; +import { artifacts } from '../../src/utils/artifacts'; +import { chaiSetup } from '../../src/utils/chai_setup'; +import { constants } from '../../src/utils/constants'; +import { AssetProxyId } from '../../src/utils/types'; +import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe.only('AssetProxyDecoder', () => { + let owner: string; + let testAssetProxyDecoder: TestLibAssetProxyDecoderContract; + + before(async () => { + // Setup accounts & addresses + const accounts = await web3Wrapper.getAvailableAddressesAsync(); + owner = accounts[0]; + // Deploy TestLibMem + testAssetProxyDecoder = await TestLibAssetProxyDecoderContract.deployFrom0xArtifactAsync( + artifacts.TestLibAssetProxyDecoder, + provider, + txDefaults, + ); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + + describe('LibAssetProxyDecoder', () => { + /*it('should )', async () => { + await testAssetProxyDecoder.test1.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test2.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test3.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test4.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test5.sendTransactionAsync(); + }); + + it('should )', async () => { + await testLibMem.test6.sendTransactionAsync(); + }); + + it('should )', async () => { + return expect(testLibMem.test7.sendTransactionAsync()).to.be.rejectedWith(constants.REVERT); + });*/ + }); +}); diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index c861484f3..6ce4ab9b6 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -18,7 +18,7 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -describe.only('LibMem', () => { +describe('LibMem', () => { let owner: string; let testLibMem: TestLibMemContract; diff --git a/packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json b/packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json new file mode 100644 index 000000000..0437766c7 --- /dev/null +++ b/packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json @@ -0,0 +1,88 @@ +{ + "schemaVersion": "2.0.0", + "contractName": "TestLibAssetProxyDecoder", + "compilerOutput": { + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "proxyData", + "type": "bytes" + } + ], + "name": "publicDecodeERC20Data", + "outputs": [ + { + "name": "", + "type": "uint8" + }, + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + } + ], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "0x608060405234801561001057600080fd5b506103a7806100206000396000f3006080604052600436106100275763ffffffff60e060020a600035041663bd27c22d811461002c575b600080fd5b34801561003857600080fd5b5061004c610047366004610208565b610063565b60405161005a9291906102a9565b60405180910390f35b60008061006f83610078565b91509150915091565b6000808251601514606060405190810160405280602281526020017f4d65746164617461206d75737420686176652061206c656e677468206f662032815260200160f160020a611897028152509015156100f15760405160e560020a62461bcd0281526004016100e89190610291565b60405180910390fd5b5082600081518110151561010157fe5b016020015160f860020a90819004810204915061011f836001610126565b9050915091565b60008160140183511015606060405190810160405280602b81526020017f4c656e677468206d7573742062652067726561746572207468616e206f722065815260200160a960020a6a38bab0b6103a3790191817028152509015156101a15760405160e560020a62461bcd0281526004016100e89190610291565b50500160140151600160a060020a031690565b6000601f820183136101c557600080fd5b81356101d86101d3826102ea565b6102c4565b915080825260208301602083018583830111156101f457600080fd5b6101ff838284610327565b50505092915050565b60006020828403121561021a57600080fd5b81356001604060020a0381111561023057600080fd5b61023c848285016101b4565b949350505050565b61024d81610315565b82525050565b600061025e82610311565b808452610272816020860160208601610333565b61027b81610363565b9093016020019392505050565b61024d81610321565b602080825281016102a28184610253565b9392505050565b604081016102b78285610288565b6102a26020830184610244565b6040518181016001604060020a03811182821017156102e257600080fd5b604052919050565b60006001604060020a0382111561030057600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b60ff1690565b82818337506000910152565b60005b8381101561034e578181015183820152602001610336565b8381111561035d576000848401525b50505050565b601f01601f1916905600a265627a7a7230582008b76108b6bf36a2766e799f617e47a5feab326e99d46ea5c5bcb8d7dfc682db6c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x3A7 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x27 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0xBD27C22D DUP2 EQ PUSH2 0x2C JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x38 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x4C PUSH2 0x47 CALLDATASIZE PUSH1 0x4 PUSH2 0x208 JUMP JUMPDEST PUSH2 0x63 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x5A SWAP3 SWAP2 SWAP1 PUSH2 0x2A9 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x6F DUP4 PUSH2 0x78 JUMP JUMPDEST SWAP2 POP SWAP2 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 MLOAD PUSH1 0x15 EQ PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662032 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xF1 PUSH1 0x2 EXP PUSH2 0x1897 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xF1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP2 POP PUSH2 0x11F DUP4 PUSH1 0x1 PUSH2 0x126 JUMP JUMPDEST SWAP1 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4C656E677468206D7573742062652067726561746572207468616E206F722065 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790191817 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x1A1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST POP POP ADD PUSH1 0x14 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x1C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x1D8 PUSH2 0x1D3 DUP3 PUSH2 0x2EA JUMP JUMPDEST PUSH2 0x2C4 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x1F4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1FF DUP4 DUP3 DUP5 PUSH2 0x327 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x21A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH2 0x230 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x23C DUP5 DUP3 DUP6 ADD PUSH2 0x1B4 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x315 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x25E DUP3 PUSH2 0x311 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x272 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x333 JUMP JUMPDEST PUSH2 0x27B DUP2 PUSH2 0x363 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x321 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x2A2 DUP2 DUP5 PUSH2 0x253 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x2B7 DUP3 DUP6 PUSH2 0x288 JUMP JUMPDEST PUSH2 0x2A2 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x244 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x2E2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH2 0x300 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x34E JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x336 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x35D JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x1F NOT AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 ADDMOD 0xb7 PUSH2 0x8B6 0xbf CALLDATASIZE LOG2 PUSH23 0x6E799F617E47A5FEAB326E99D46EA5C5BCB8D7DFC682DB PUSH13 0x6578706572696D656E74616CF5 STOP CALLDATACOPY ", + "sourceMap": "709:592:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;709:592:0;;;;;;;" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "0x6080604052600436106100275763ffffffff60e060020a600035041663bd27c22d811461002c575b600080fd5b34801561003857600080fd5b5061004c610047366004610208565b610063565b60405161005a9291906102a9565b60405180910390f35b60008061006f83610078565b91509150915091565b6000808251601514606060405190810160405280602281526020017f4d65746164617461206d75737420686176652061206c656e677468206f662032815260200160f160020a611897028152509015156100f15760405160e560020a62461bcd0281526004016100e89190610291565b60405180910390fd5b5082600081518110151561010157fe5b016020015160f860020a90819004810204915061011f836001610126565b9050915091565b60008160140183511015606060405190810160405280602b81526020017f4c656e677468206d7573742062652067726561746572207468616e206f722065815260200160a960020a6a38bab0b6103a3790191817028152509015156101a15760405160e560020a62461bcd0281526004016100e89190610291565b50500160140151600160a060020a031690565b6000601f820183136101c557600080fd5b81356101d86101d3826102ea565b6102c4565b915080825260208301602083018583830111156101f457600080fd5b6101ff838284610327565b50505092915050565b60006020828403121561021a57600080fd5b81356001604060020a0381111561023057600080fd5b61023c848285016101b4565b949350505050565b61024d81610315565b82525050565b600061025e82610311565b808452610272816020860160208601610333565b61027b81610363565b9093016020019392505050565b61024d81610321565b602080825281016102a28184610253565b9392505050565b604081016102b78285610288565b6102a26020830184610244565b6040518181016001604060020a03811182821017156102e257600080fd5b604052919050565b60006001604060020a0382111561030057600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b60ff1690565b82818337506000910152565b60005b8381101561034e578181015183820152602001610336565b8381111561035d576000848401525b50505050565b601f01601f1916905600a265627a7a7230582008b76108b6bf36a2766e799f617e47a5feab326e99d46ea5c5bcb8d7dfc682db6c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x27 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0xBD27C22D DUP2 EQ PUSH2 0x2C JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x38 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x4C PUSH2 0x47 CALLDATASIZE PUSH1 0x4 PUSH2 0x208 JUMP JUMPDEST PUSH2 0x63 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x5A SWAP3 SWAP2 SWAP1 PUSH2 0x2A9 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x6F DUP4 PUSH2 0x78 JUMP JUMPDEST SWAP2 POP SWAP2 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 MLOAD PUSH1 0x15 EQ PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662032 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xF1 PUSH1 0x2 EXP PUSH2 0x1897 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xF1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP2 POP PUSH2 0x11F DUP4 PUSH1 0x1 PUSH2 0x126 JUMP JUMPDEST SWAP1 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4C656E677468206D7573742062652067726561746572207468616E206F722065 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790191817 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x1A1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST POP POP ADD PUSH1 0x14 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x1C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x1D8 PUSH2 0x1D3 DUP3 PUSH2 0x2EA JUMP JUMPDEST PUSH2 0x2C4 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x1F4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1FF DUP4 DUP3 DUP5 PUSH2 0x327 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x21A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH2 0x230 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x23C DUP5 DUP3 DUP6 ADD PUSH2 0x1B4 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x315 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x25E DUP3 PUSH2 0x311 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x272 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x333 JUMP JUMPDEST PUSH2 0x27B DUP2 PUSH2 0x363 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x321 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x2A2 DUP2 DUP5 PUSH2 0x253 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x2B7 DUP3 DUP6 PUSH2 0x288 JUMP JUMPDEST PUSH2 0x2A2 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x244 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x2E2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH2 0x300 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x34E JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x336 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x35D JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x1F NOT AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 ADDMOD 0xb7 PUSH2 0x8B6 0xbf CALLDATASIZE LOG2 PUSH23 0x6E799F617E47A5FEAB326E99D46EA5C5BCB8D7DFC682DB PUSH13 0x6578706572696D656E74616CF5 STOP CALLDATACOPY ", + "sourceMap": "709:592:0:-;;;;;;;;;-1:-1:-1;;;709:592:0;;;;;;;;;;;;;823:170;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;823:170:0;;;;;;;;;;;;;;;;;;;;;;;;;;;923:5;930:7;960:26;976:9;960:15;:26::i;:::-;953:33;;;;823:170;;;:::o;965:393:1:-;1074:13;1101;1160:9;:16;1180:2;1160:22;1196:29;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1196:29:1;;;1139:96;;;;;;;-1:-1:-1;;;;;1139:96:1;;;;;;;;;;;;;;;;;;;1261:9;1271:1;1261:12;;;;;;;;;;;;;;-1:-1:-1;;;1261:12:1;;;;;;1255:19;;-1:-1:-1;1292:25:1;1304:9;1315:1;1292:11;:25::i;:::-;1284:33;-1:-1:-1;965:393:1;;;:::o;2204:868:2:-;2325:14;2388:5;2396:2;2388:10;2376:1;:8;:22;;2440;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2440:22:2;;;2355:117;;;;;;;-1:-1:-1;;;;;2355:117:2;;;;;;;;;;-1:-1:-1;;2974:13:2;2719:2;2974:13;2968:20;-1:-1:-1;;;;;2964:69:2;;2204:868::o;6:440:-1:-;;100:4;88:17;;84:27;-1:-1;74:2;;125:1;122;115:12;74:2;162:6;149:20;184:64;199:48;240:6;199:48;;;184:64;;;175:73;;268:6;261:5;254:21;304:4;296:6;292:17;337:4;330:5;326:16;372:3;363:6;358:3;354:16;351:25;348:2;;;389:1;386;379:12;348:2;399:41;433:6;428:3;423;399:41;;;67:379;;;;;;;;454:345;;567:2;555:9;546:7;542:23;538:32;535:2;;;583:1;580;573:12;535:2;618:31;;-1:-1;;;;;658:30;;655:2;;;701:1;698;691:12;655:2;721:62;775:7;766:6;755:9;751:22;721:62;;;711:72;529:270;-1:-1;;;;529:270;806:110;879:31;904:5;879:31;;;874:3;867:44;861:55;;;923:292;;1021:35;1050:5;1021:35;;;1073:6;1068:3;1061:19;1085:63;1141:6;1134:4;1129:3;1125:14;1118:4;1111:5;1107:16;1085:63;;;1180:29;1202:6;1180:29;;;1160:50;;;1173:4;1160:50;;1001:214;-1:-1;;;1001:214;1222:104;1291:29;1314:5;1291:29;;1333:273;1457:2;1471:47;;;1442:18;;1532:64;1442:18;1582:6;1532:64;;;1524:72;1428:178;-1:-1;;;1428:178;1613:286;1745:2;1730:18;;1759:57;1734:9;1789:6;1759:57;;;1827:62;1885:2;1874:9;1870:18;1861:6;1827:62;;1906:256;1968:2;1962:9;1994:17;;;-1:-1;;;;;2054:34;;2090:22;;;2051:62;2048:2;;;2126:1;2123;2116:12;2048:2;2142;2135:22;1946:216;;-1:-1;1946:216;2169:258;;-1:-1;;;;;2304:6;2301:30;2298:2;;;2344:1;2341;2334:12;2298:2;-1:-1;2417:4;2388;2365:17;;;;-1:-1;;2361:33;2407:15;;2235:192;2434:88;2505:12;;2489:33;2529:128;-1:-1;;;;;2598:54;;2581:76;2664:88;2742:4;2731:16;;2714:38;2760:145;2841:6;2836:3;2831;2818:30;-1:-1;2897:1;2879:16;;2872:27;2811:94;2914:268;2979:1;2986:101;3000:6;2997:1;2994:13;2986:101;;;3067:11;;;3061:18;3048:11;;;3041:39;3022:2;3015:10;2986:101;;;3102:6;3099:1;3096:13;3093:2;;;3167:1;3158:6;3153:3;3149:16;3142:27;3093:2;2963:219;;;;;3190:97;3278:2;3258:14;-1:-1;;3254:28;;3238:49" + } + } + }, + "sources": { + "current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol": { + "id": 0 + }, + "current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol": { + "id": 1 + }, + "current/utils/LibBytes/LibBytes.sol": { + "id": 2 + }, + "current/utils/LibMem/LibMem.sol": { + "id": 3 + } + }, + "sourceCodes": { + "current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol\";\n\ncontract TestLibAssetProxyDecoder is\n LibAssetProxyDecoder\n{\n\n /// @dev Decodes ERC721 Asset Proxy data\n function publicDecodeERC20Data(bytes memory proxyData)\n public\n pure\n returns (uint8, address)\n {\n return decodeERC20Data(proxyData);\n }\n\n /// @dev Decodes ERC721 Asset Proxy data\n function publicDecodeERC721Data(bytes memory proxyData)\n internal\n pure\n returns (\n uint8,\n address,\n uint256,\n bytes memory\n )\n {\n return decodeERC721Data(proxyData);\n }\n}\n", + "current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../LibBytes/LibBytes.sol\";\n\ncontract LibAssetProxyDecoder is\n LibBytes\n{\n\n string constant INVALID_ERC20_METADATA_LENGTH = \"Metadata must have a length of 21.\";\n string constant INVALID_ERC721_METADATA_LENGTH = \"Metadata must have a length of at least 53.\";\n\n /// @dev Decodes ERC721 Asset Proxy data\n function decodeERC20Data(bytes memory proxyData)\n internal\n pure\n returns (\n uint8 proxyId,\n address token\n )\n {\n require(\n proxyData.length == 21,\n INVALID_ERC20_METADATA_LENGTH\n );\n proxyId = uint8(proxyData[0]);\n token = readAddress(proxyData, 1);\n\n return (proxyId, token);\n }\n\n /// @dev Decodes ERC721 Asset Proxy data\n function decodeERC721Data(bytes memory proxyData)\n internal\n pure\n returns (\n uint8 proxyId,\n address token,\n uint256 tokenId,\n bytes memory data\n )\n {\n require(\n proxyData.length >= 53,\n INVALID_ERC721_METADATA_LENGTH\n );\n proxyId = uint8(proxyData[0]);\n token = readAddress(proxyData, 1);\n tokenId = readUint256(proxyData, 21);\n if (proxyData.length > 53) {\n data = readBytes(proxyData, 53);\n }\n\n return (proxyId, token, tokenId, data);\n }\n}\n", + "current/utils/LibBytes/LibBytes.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\n\nimport \"../LibMem/LibMem.sol\";\n\ncontract LibBytes is\n LibMem\n{\n\n // Revert reasons\n string constant GTE_20_LENGTH_REQUIRED = \"Length must be greater than or equal to 20.\";\n string constant GTE_32_LENGTH_REQUIRED = \"Length must be greater than or equal to 32.\";\n\n /// @dev Tests equality of two byte arrays.\n /// @param lhs First byte array to compare.\n /// @param rhs Second byte array to compare.\n /// @return True if arrays are the same. False otherwise.\n function areBytesEqual(bytes memory lhs, bytes memory rhs)\n internal\n pure\n returns (bool equal)\n {\n assembly {\n // Get the number of words occupied by \n let lenFullWords := div(add(mload(lhs), 0x1F), 0x20)\n\n // Add 1 to the number of words, to account for the length field\n lenFullWords := add(lenFullWords, 0x1)\n\n // Test equality word-by-word.\n // Terminates early if there is a mismatch.\n for {let i := 0} lt(i, lenFullWords) {i := add(i, 1)} {\n let lhsWord := mload(add(lhs, mul(i, 0x20)))\n let rhsWord := mload(add(rhs, mul(i, 0x20)))\n equal := eq(lhsWord, rhsWord)\n if eq(equal, 0) {\n // Break\n i := lenFullWords\n }\n }\n }\n\n return equal;\n }\n\n /// @dev Reads an address from a position in a byte array.\n /// @param b Byte array containing an address.\n /// @param index Index in byte array of address.\n /// @return address from byte array.\n function readAddress(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (address result)\n {\n require(\n b.length >= index + 20, // 20 is length of address\n GTE_20_LENGTH_REQUIRED\n );\n\n // Add offset to index:\n // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)\n // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)\n index += 20;\n\n // Read address from array memory\n assembly {\n // 1. Add index to address of bytes array\n // 2. Load 32-byte word from memory\n // 3. Apply 20-byte mask to obtain address\n result := and(mload(add(b, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n }\n return result;\n }\n\n /// @dev Writes an address into a specific position in a byte array.\n /// @param b Byte array to insert address into.\n /// @param index Index in byte array of address.\n /// @param input Address to put into byte array.\n function writeAddress(\n bytes memory b,\n uint256 index,\n address input\n )\n internal\n pure\n {\n require(\n b.length >= index + 20, // 20 is length of address\n GTE_20_LENGTH_REQUIRED\n );\n\n // Add offset to index:\n // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)\n // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)\n index += 20;\n\n // Store address into array memory\n assembly {\n // The address occupies 20 bytes and mstore stores 32 bytes.\n // First fetch the 32-byte word where we'll be storing the address, then\n // apply a mask so we have only the bytes in the word that the address will not occupy.\n // Then combine these bytes with the address and store the 32 bytes back to memory with mstore.\n\n // 1. Add index to address of bytes array\n // 2. Load 32-byte word from memory\n // 3. Apply 12-byte mask to obtain extra bytes occupying word of memory where we'll store the address\n let neighbors := and(mload(add(b, index)), 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)\n\n // Store the neighbors and address into memory\n mstore(add(b, index), xor(input, neighbors))\n }\n }\n\n /// @dev Reads a bytes32 value from a position in a byte array.\n /// @param b Byte array containing a bytes32 value.\n /// @param index Index in byte array of bytes32 value.\n /// @return bytes32 value from byte array.\n function readBytes32(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (bytes32 result)\n {\n require(\n b.length >= index + 32,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Arrays are prefixed by a 256 bit length parameter\n index += 32;\n\n // Read the bytes32 from array memory\n assembly {\n result := mload(add(b, index))\n }\n return result;\n }\n\n /// @dev Writes a bytes32 into a specific position in a byte array.\n /// @param b Byte array to insert into.\n /// @param index Index in byte array of .\n /// @param input bytes32 to put into byte array.\n function writeBytes32(\n bytes memory b,\n uint256 index,\n bytes32 input\n )\n internal\n pure\n {\n require(\n b.length >= index + 32,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Arrays are prefixed by a 256 bit length parameter\n index += 32;\n\n // Read the bytes32 from array memory\n assembly {\n mstore(add(b, index), input)\n }\n }\n\n /// @dev Reads a uint256 value from a position in a byte array.\n /// @param b Byte array containing a uint256 value.\n /// @param index Index in byte array of uint256 value.\n /// @return uint256 value from byte array.\n function readUint256(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (uint256 result)\n {\n return uint256(readBytes32(b, index));\n }\n\n /// @dev Writes a uint256 into a specific position in a byte array.\n /// @param b Byte array to insert into.\n /// @param index Index in byte array of .\n /// @param input uint256 to put into byte array.\n function writeUint256(\n bytes memory b,\n uint256 index,\n uint256 input\n )\n internal\n pure\n {\n writeBytes32(b, index, bytes32(input));\n }\n\n /// @dev Reads a uint256 value from a position in a byte array.\n /// @param b Byte array containing a uint256 value.\n /// @param index Index in byte array of uint256 value.\n /// @return uint256 value from byte array.\n function readBytes(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (bytes memory result)\n {\n // Read length of nested bytes\n require(\n b.length >= index + 32,\n GTE_32_LENGTH_REQUIRED\n );\n uint256 nestedBytesLength = readUint256(b, index);\n\n // Assert length of is valid, given\n // length of nested bytes\n require(\n b.length >= index + 32 + nestedBytesLength,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Allocate memory and copy value to result\n result = new bytes(nestedBytesLength);\n memcpy(\n getMemAddress(result) + 32, // +32 skips array length\n getMemAddress(b) + index + 32, // +32 skips array length\n nestedBytesLength\n );\n\n return result;\n }\n\n /// @dev Writes a uint256 into a specific position in a byte array.\n /// @param b Byte array to insert into.\n /// @param index Index in byte array of .\n /// @param input uint256 to put into byte array.\n function writeBytes(\n bytes memory b,\n uint256 index,\n bytes memory input\n )\n internal\n pure\n {\n // Read length of nested bytes\n require(\n b.length >= index + 32 /* 32 bytes to store length */ + input.length,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Copy into \n memcpy(\n getMemAddress(b) + index,\n getMemAddress(input),\n input.length + 32 /* 32 bytes to store length */\n );\n }\n}\n", + "current/utils/LibMem/LibMem.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\n\ncontract LibMem {\n\n function getMemAddress(bytes memory input)\n internal\n pure\n returns (uint256 address_)\n {\n assembly {\n address_ := input\n }\n return address_;\n }\n\n /// @dev Writes a uint256 into a specific position in a byte array.\n /// @param dest memory adress to copy bytes to\n function memcpy(\n uint256 dest,\n uint256 source,\n uint256 length\n )\n internal\n pure\n {\n // Base cases\n if(length == 0) return;\n if(source == dest) return;\n\n // Copy bytes from source to dest\n assembly {\n // Compute number of complete words to copy + remaining bytes\n let lenFullWords := div(add(length, 0x1F), 0x20)\n let remainder := mod(length, 0x20)\n if gt(remainder, 0) {\n lenFullWords := sub(lenFullWords, 1)\n }\n\n // Copy full words from source to dest\n let offset := 0\n let maxOffset := mul(0x20, lenFullWords)\n for {offset := 0} lt(offset, maxOffset) {offset := add(offset, 0x20)} {\n mstore(add(dest, offset), mload(add(source, offset)))\n }\n\n // Copy remaining bytes\n if gt(remainder, 0) {\n // Read a full word from source, containing X bytes to copy to dest.\n // We only want to keep the X bytes, zeroing out the remaining bytes.\n // We accomplish this by a right shift followed by a left shift.\n // Example:\n // Suppose a word of 8 bits has all 1's: [11111111]\n // Let X = 7 (we want to copy the first 7 bits)\n // Apply a right shift of 1: [01111111]\n // Apply a left shift of 1: [11111110]\n let sourceShiftFactor := exp(2, mul(8, sub(0x20, remainder)))\n let sourceWord := mload(add(source, offset))\n let sourceBytes := mul(div(sourceWord, sourceShiftFactor), sourceShiftFactor)\n\n // Read a full word from dest, containing (32-X) bytes to retain.\n // We need to zero out the remaining bytes to be overwritten by source,\n // while retaining the (32-X) bytes we don't want to overwrite.\n // We accomplish this by a left shift followed by a right shift.\n // Example:\n // Suppose a word of 8 bits has all 1's: [11111111]\n // Let X = 7 (we want to free the first 7 bits, and retain the last bit)\n // Apply a left shift of 1: [11111110]\n // Apply a right shift of 1: [01111111]\n let destShiftFactor := exp(2, mul(8, remainder))\n let destWord := mload(add(dest, offset))\n let destBytes := div(mul(destWord, destShiftFactor), destShiftFactor)\n\n // Combine the source and dest bytes. There should be no overlap:\n // The source bytes run from [0..X-1] and the dest bytes from [X..31].\n // Example:\n // Following the example from above, we have [11111110]\n // from the source word and [01111111] from the dest word.\n // Combine these words using to get [11111111].\n let combinedDestWord := or(sourceBytes, destBytes)\n\n // Store the combined word into dest\n mstore(add(dest, offset), combinedDestWord)\n }\n }\n }\n}\n" + }, + "sourceTreeHashHex": "0x8431fff2ae9424603c06a10d9c4649edf92a798a8969fe69339fc0063b7ad144", + "compiler": { + "name": "solc", + "version": "0.4.24", + "settings": { + "optimizer": { + "enabled": true, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap" + ] + } + } + } + }, + "networks": {} +} \ No newline at end of file -- cgit v1.2.3 From bc0edd40427944349ac0c3e367c9638a1c7797dd Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 24 May 2018 13:03:17 -0700 Subject: LibAssetProxyDecoder tests --- .../TestLibAssetProxyDecoder.sol | 2 +- packages/contracts/test/asset_proxy/decoder.ts | 56 ++++++++++++---------- .../artifacts/2.0.0/TestLibAssetProxyDecoder.json | 47 ++++++++++++++---- 3 files changed, 70 insertions(+), 35 deletions(-) diff --git a/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol b/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol index ac7cd63ab..e4a7de71d 100644 --- a/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol +++ b/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol @@ -36,7 +36,7 @@ contract TestLibAssetProxyDecoder is /// @dev Decodes ERC721 Asset Proxy data function publicDecodeERC721Data(bytes memory proxyData) - internal + public pure returns ( uint8, diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 74e7547d3..b35cd0d43 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -9,23 +9,26 @@ import * as Web3 from 'web3'; import { TestLibAssetProxyDecoderContract } from '../../src/contract_wrappers/generated/test_lib_asset_proxy_decoder'; import { artifacts } from '../../src/utils/artifacts'; +import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; -import { AssetProxyId } from '../../src/utils/types'; +import { AssetProxyId, ERC20ProxyData, ERC721ProxyData, ProxyData } from '../../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -describe.only('AssetProxyDecoder', () => { +describe.only('LibAssetProxyDecoder', () => { let owner: string; let testAssetProxyDecoder: TestLibAssetProxyDecoderContract; + let testAddress: string; before(async () => { // Setup accounts & addresses const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = accounts[0]; + testAddress = accounts[1]; // Deploy TestLibMem testAssetProxyDecoder = await TestLibAssetProxyDecoderContract.deployFrom0xArtifactAsync( artifacts.TestLibAssetProxyDecoder, @@ -41,32 +44,33 @@ describe.only('AssetProxyDecoder', () => { }); describe('LibAssetProxyDecoder', () => { - /*it('should )', async () => { - await testAssetProxyDecoder.test1.sendTransactionAsync(); + it('should correctly decode ERC20 proxy data)', async () => { + const encodedProxyData = assetProxyUtils.encodeERC20ProxyData(testAddress); + const expectedDecodedProxyData = assetProxyUtils.decodeERC20ProxyData(encodedProxyData); + let decodedAssetProxyId: number; + let decodedTokenAddress: string; + [decodedAssetProxyId, decodedTokenAddress] = await testAssetProxyDecoder.publicDecodeERC20Data.callAsync( + encodedProxyData, + ); + expect(decodedAssetProxyId).to.be.equal(expectedDecodedProxyData.assetProxyId); + expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); }); - it('should )', async () => { - await testLibMem.test2.sendTransactionAsync(); + it('should correctly decode ERC721 proxy data)', async () => { + const tokenId = ZeroEx.generatePseudoRandomSalt(); + const encodedProxyData = assetProxyUtils.encodeERC721ProxyData(testAddress, tokenId); + const expectedDecodedProxyData = assetProxyUtils.decodeERC721ProxyData(encodedProxyData); + let decodedAssetProxyId: number; + let decodedTokenAddress: string; + let decodedTokenId: BigNumber; + [ + decodedAssetProxyId, + decodedTokenAddress, + decodedTokenId, + ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedProxyData); + expect(decodedAssetProxyId).to.be.equal(expectedDecodedProxyData.assetProxyId); + expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); + expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedProxyData.tokenId); }); - - it('should )', async () => { - await testLibMem.test3.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test4.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test5.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test6.sendTransactionAsync(); - }); - - it('should )', async () => { - return expect(testLibMem.test7.sendTransactionAsync()).to.be.rejectedWith(constants.REVERT); - });*/ }); }); diff --git a/packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json b/packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json index 0437766c7..40790e39f 100644 --- a/packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json +++ b/packages/migrations/artifacts/2.0.0/TestLibAssetProxyDecoder.json @@ -3,6 +3,37 @@ "contractName": "TestLibAssetProxyDecoder", "compilerOutput": { "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "proxyData", + "type": "bytes" + } + ], + "name": "publicDecodeERC721Data", + "outputs": [ + { + "name": "", + "type": "uint8" + }, + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, { "constant": true, "inputs": [ @@ -30,15 +61,15 @@ "evm": { "bytecode": { "linkReferences": {}, - "object": "0x608060405234801561001057600080fd5b506103a7806100206000396000f3006080604052600436106100275763ffffffff60e060020a600035041663bd27c22d811461002c575b600080fd5b34801561003857600080fd5b5061004c610047366004610208565b610063565b60405161005a9291906102a9565b60405180910390f35b60008061006f83610078565b91509150915091565b6000808251601514606060405190810160405280602281526020017f4d65746164617461206d75737420686176652061206c656e677468206f662032815260200160f160020a611897028152509015156100f15760405160e560020a62461bcd0281526004016100e89190610291565b60405180910390fd5b5082600081518110151561010157fe5b016020015160f860020a90819004810204915061011f836001610126565b9050915091565b60008160140183511015606060405190810160405280602b81526020017f4c656e677468206d7573742062652067726561746572207468616e206f722065815260200160a960020a6a38bab0b6103a3790191817028152509015156101a15760405160e560020a62461bcd0281526004016100e89190610291565b50500160140151600160a060020a031690565b6000601f820183136101c557600080fd5b81356101d86101d3826102ea565b6102c4565b915080825260208301602083018583830111156101f457600080fd5b6101ff838284610327565b50505092915050565b60006020828403121561021a57600080fd5b81356001604060020a0381111561023057600080fd5b61023c848285016101b4565b949350505050565b61024d81610315565b82525050565b600061025e82610311565b808452610272816020860160208601610333565b61027b81610363565b9093016020019392505050565b61024d81610321565b602080825281016102a28184610253565b9392505050565b604081016102b78285610288565b6102a26020830184610244565b6040518181016001604060020a03811182821017156102e257600080fd5b604052919050565b60006001604060020a0382111561030057600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b60ff1690565b82818337506000910152565b60005b8381101561034e578181015183820152602001610336565b8381111561035d576000848401525b50505050565b601f01601f1916905600a265627a7a7230582008b76108b6bf36a2766e799f617e47a5feab326e99d46ea5c5bcb8d7dfc682db6c6578706572696d656e74616cf50037", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x3A7 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x27 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0xBD27C22D DUP2 EQ PUSH2 0x2C JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x38 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x4C PUSH2 0x47 CALLDATASIZE PUSH1 0x4 PUSH2 0x208 JUMP JUMPDEST PUSH2 0x63 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x5A SWAP3 SWAP2 SWAP1 PUSH2 0x2A9 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x6F DUP4 PUSH2 0x78 JUMP JUMPDEST SWAP2 POP SWAP2 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 MLOAD PUSH1 0x15 EQ PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662032 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xF1 PUSH1 0x2 EXP PUSH2 0x1897 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xF1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP2 POP PUSH2 0x11F DUP4 PUSH1 0x1 PUSH2 0x126 JUMP JUMPDEST SWAP1 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4C656E677468206D7573742062652067726561746572207468616E206F722065 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790191817 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x1A1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST POP POP ADD PUSH1 0x14 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x1C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x1D8 PUSH2 0x1D3 DUP3 PUSH2 0x2EA JUMP JUMPDEST PUSH2 0x2C4 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x1F4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1FF DUP4 DUP3 DUP5 PUSH2 0x327 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x21A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH2 0x230 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x23C DUP5 DUP3 DUP6 ADD PUSH2 0x1B4 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x315 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x25E DUP3 PUSH2 0x311 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x272 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x333 JUMP JUMPDEST PUSH2 0x27B DUP2 PUSH2 0x363 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x321 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x2A2 DUP2 DUP5 PUSH2 0x253 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x2B7 DUP3 DUP6 PUSH2 0x288 JUMP JUMPDEST PUSH2 0x2A2 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x244 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x2E2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH2 0x300 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x34E JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x336 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x35D JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x1F NOT AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 ADDMOD 0xb7 PUSH2 0x8B6 0xbf CALLDATASIZE LOG2 PUSH23 0x6E799F617E47A5FEAB326E99D46EA5C5BCB8D7DFC682DB PUSH13 0x6578706572696D656E74616CF5 STOP CALLDATACOPY ", - "sourceMap": "709:592:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;709:592:0;;;;;;;" + "object": "0x608060405234801561001057600080fd5b50610791806100206000396000f3006080604052600436106100325763ffffffff60e060020a60003504166372c2f5278114610037578063bd27c22d14610070575b600080fd5b34801561004357600080fd5b5061005761005236600461058c565b61009e565b604051610067949392919061064a565b60405180910390f35b34801561007c57600080fd5b5061009061008b36600461058c565b6100bd565b60405161006792919061062f565b600080600060606100ae856100d2565b93509350935093509193509193565b6000806100c9836101b5565b91509150915091565b60008060006060603585511015606060405190810160405280602b81526020017f4d65746164617461206d75737420686176652061206c656e677468206f662061815260200160a960020a6a3a103632b0b9ba101a9997028152509015156101595760405160e560020a62461bcd028152600401610150919061061e565b60405180910390fd5b5084600081518110151561016957fe5b016020015160f860020a90819004810204935061018785600161025a565b92506101948560156102d6565b91506035855111156101ae576101ab8560356102e9565b90505b9193509193565b6000808251601514606060405190810160405280602281526020017f4d65746164617461206d75737420686176652061206c656e677468206f662032815260200160f160020a611897028152509015156102255760405160e560020a62461bcd028152600401610150919061061e565b5082600081518110151561023557fe5b016020015160f860020a90819004810204915061025383600161025a565b9050915091565b60008160140183511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a3790191817028152509015156102c35760405160e560020a62461bcd028152600401610150919061061e565b50500160140151600160a060020a031690565b60006102e28383610426565b9392505050565b606060008260200184511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a3790199917028152509015156103545760405160e560020a62461bcd028152600401610150919061061e565b5061035f84846102d6565b905080836020010184511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a3790199917028152509015156103ca5760405160e560020a62461bcd028152600401610150919061061e565b50806040519080825280601f01601f1916602001820160405280156103f9578160200160208202803883390190505b50915061041f61040883610499565b6020018461041587610499565b016020018361049c565b5092915050565b60008160200183511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a37901999170281525090151561048f5760405160e560020a62461bcd028152600401610150919061061e565b5050016020015190565b90565b8015156104a857610533565b828214156104b557610533565b6020601f8201046020820660008111156104d0576001820391505b6000602083025b808210156104f25781860151828801526020820191506104d7565b600083111561052e578260200360080260020a8287015181828204028560080260020a858b0151818282020480841780898f0152505050505050505b505050505b505050565b6000601f8201831361054957600080fd5b813561055c610557826106b4565b61068e565b9150808252602083016020830185838301111561057857600080fd5b6105838382846106f1565b50505092915050565b60006020828403121561059e57600080fd5b81356001604060020a038111156105b457600080fd5b6105c084828501610538565b949350505050565b6105d1816106df565b82525050565b60006105e2826106db565b8084526105f68160208601602086016106fd565b6105ff8161072d565b9093016020019392505050565b6105d181610499565b6105d1816106eb565b602080825281016102e281846105d7565b6040810161063d8285610615565b6102e260208301846105c8565b608081016106588287610615565b61066560208301866105c8565b610672604083018561060c565b818103606083015261068481846105d7565b9695505050505050565b6040518181016001604060020a03811182821017156106ac57600080fd5b604052919050565b60006001604060020a038211156106ca57600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b60ff1690565b82818337506000910152565b60005b83811015610718578181015183820152602001610700565b83811115610727576000848401525b50505050565b601f01601f19169056004c656e677468206d7573742062652067726561746572207468616e206f722065a265627a7a723058205132eb7448f5b6279dedd3c042e96fb9ea0d8a8aea79044353638cf00546165f6c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x791 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x32 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x72C2F527 DUP2 EQ PUSH2 0x37 JUMPI DUP1 PUSH4 0xBD27C22D EQ PUSH2 0x70 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x43 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x57 PUSH2 0x52 CALLDATASIZE PUSH1 0x4 PUSH2 0x58C JUMP JUMPDEST PUSH2 0x9E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x67 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x64A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x7C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x90 PUSH2 0x8B CALLDATASIZE PUSH1 0x4 PUSH2 0x58C JUMP JUMPDEST PUSH2 0xBD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x67 SWAP3 SWAP2 SWAP1 PUSH2 0x62F JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 PUSH2 0xAE DUP6 PUSH2 0xD2 JUMP JUMPDEST SWAP4 POP SWAP4 POP SWAP4 POP SWAP4 POP SWAP2 SWAP4 POP SWAP2 SWAP4 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH2 0xC9 DUP4 PUSH2 0x1B5 JUMP JUMPDEST SWAP2 POP SWAP2 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 PUSH1 0x35 DUP6 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662061 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x3A103632B0B9BA101A9997 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x159 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP5 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x169 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP4 POP PUSH2 0x187 DUP6 PUSH1 0x1 PUSH2 0x25A JUMP JUMPDEST SWAP3 POP PUSH2 0x194 DUP6 PUSH1 0x15 PUSH2 0x2D6 JUMP JUMPDEST SWAP2 POP PUSH1 0x35 DUP6 MLOAD GT ISZERO PUSH2 0x1AE JUMPI PUSH2 0x1AB DUP6 PUSH1 0x35 PUSH2 0x2E9 JUMP JUMPDEST SWAP1 POP JUMPDEST SWAP2 SWAP4 POP SWAP2 SWAP4 JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 MLOAD PUSH1 0x15 EQ PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662032 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xF1 PUSH1 0x2 EXP PUSH2 0x1897 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x225 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP DUP3 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x235 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP2 POP PUSH2 0x253 DUP4 PUSH1 0x1 PUSH2 0x25A JUMP JUMPDEST SWAP1 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790191817 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x2C3 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP POP ADD PUSH1 0x14 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x2E2 DUP4 DUP4 PUSH2 0x426 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x0 DUP3 PUSH1 0x20 ADD DUP5 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790199917 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x354 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP PUSH2 0x35F DUP5 DUP5 PUSH2 0x2D6 JUMP JUMPDEST SWAP1 POP DUP1 DUP4 PUSH1 0x20 ADD ADD DUP5 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790199917 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x3CA JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP DUP1 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x3F9 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP2 POP PUSH2 0x41F PUSH2 0x408 DUP4 PUSH2 0x499 JUMP JUMPDEST PUSH1 0x20 ADD DUP5 PUSH2 0x415 DUP8 PUSH2 0x499 JUMP JUMPDEST ADD PUSH1 0x20 ADD DUP4 PUSH2 0x49C JUMP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790199917 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x48F JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST DUP1 ISZERO ISZERO PUSH2 0x4A8 JUMPI PUSH2 0x533 JUMP JUMPDEST DUP3 DUP3 EQ ISZERO PUSH2 0x4B5 JUMPI PUSH2 0x533 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x1F DUP3 ADD DIV PUSH1 0x20 DUP3 MOD PUSH1 0x0 DUP2 GT ISZERO PUSH2 0x4D0 JUMPI PUSH1 0x1 DUP3 SUB SWAP2 POP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP4 MUL JUMPDEST DUP1 DUP3 LT ISZERO PUSH2 0x4F2 JUMPI DUP2 DUP7 ADD MLOAD DUP3 DUP9 ADD MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH2 0x4D7 JUMP JUMPDEST PUSH1 0x0 DUP4 GT ISZERO PUSH2 0x52E JUMPI DUP3 PUSH1 0x20 SUB PUSH1 0x8 MUL PUSH1 0x2 EXP DUP3 DUP8 ADD MLOAD DUP2 DUP3 DUP3 DIV MUL DUP6 PUSH1 0x8 MUL PUSH1 0x2 EXP DUP6 DUP12 ADD MLOAD DUP2 DUP3 DUP3 MUL DIV DUP1 DUP5 OR DUP1 DUP10 DUP16 ADD MSTORE POP POP POP POP POP POP POP JUMPDEST POP POP POP POP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x549 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x55C PUSH2 0x557 DUP3 PUSH2 0x6B4 JUMP JUMPDEST PUSH2 0x68E JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x578 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x583 DUP4 DUP3 DUP5 PUSH2 0x6F1 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x59E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH2 0x5B4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x5C0 DUP5 DUP3 DUP6 ADD PUSH2 0x538 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0x5D1 DUP2 PUSH2 0x6DF JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5E2 DUP3 PUSH2 0x6DB JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x5F6 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x6FD JUMP JUMPDEST PUSH2 0x5FF DUP2 PUSH2 0x72D JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH2 0x5D1 DUP2 PUSH2 0x499 JUMP JUMPDEST PUSH2 0x5D1 DUP2 PUSH2 0x6EB JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x2E2 DUP2 DUP5 PUSH2 0x5D7 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x63D DUP3 DUP6 PUSH2 0x615 JUMP JUMPDEST PUSH2 0x2E2 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x5C8 JUMP JUMPDEST PUSH1 0x80 DUP2 ADD PUSH2 0x658 DUP3 DUP8 PUSH2 0x615 JUMP JUMPDEST PUSH2 0x665 PUSH1 0x20 DUP4 ADD DUP7 PUSH2 0x5C8 JUMP JUMPDEST PUSH2 0x672 PUSH1 0x40 DUP4 ADD DUP6 PUSH2 0x60C JUMP JUMPDEST DUP2 DUP2 SUB PUSH1 0x60 DUP4 ADD MSTORE PUSH2 0x684 DUP2 DUP5 PUSH2 0x5D7 JUMP JUMPDEST SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x6AC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH2 0x6CA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x718 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x700 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x727 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x1F NOT AND SWAP1 JUMP STOP 0x4c PUSH6 0x6E677468206D PUSH22 0x73742062652067726561746572207468616E206F7220 PUSH6 0xA265627A7A72 ADDRESS PC KECCAK256 MLOAD ORIGIN 0xeb PUSH21 0x48F5B6279DEDD3C042E96FB9EA0D8A8AEA79044353 PUSH4 0x8CF00546 AND 0x5f PUSH13 0x6578706572696D656E74616CF5 STOP CALLDATACOPY ", + "sourceMap": "709:590:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;709:590:0;;;;;;;" }, "deployedBytecode": { "linkReferences": {}, - "object": "0x6080604052600436106100275763ffffffff60e060020a600035041663bd27c22d811461002c575b600080fd5b34801561003857600080fd5b5061004c610047366004610208565b610063565b60405161005a9291906102a9565b60405180910390f35b60008061006f83610078565b91509150915091565b6000808251601514606060405190810160405280602281526020017f4d65746164617461206d75737420686176652061206c656e677468206f662032815260200160f160020a611897028152509015156100f15760405160e560020a62461bcd0281526004016100e89190610291565b60405180910390fd5b5082600081518110151561010157fe5b016020015160f860020a90819004810204915061011f836001610126565b9050915091565b60008160140183511015606060405190810160405280602b81526020017f4c656e677468206d7573742062652067726561746572207468616e206f722065815260200160a960020a6a38bab0b6103a3790191817028152509015156101a15760405160e560020a62461bcd0281526004016100e89190610291565b50500160140151600160a060020a031690565b6000601f820183136101c557600080fd5b81356101d86101d3826102ea565b6102c4565b915080825260208301602083018583830111156101f457600080fd5b6101ff838284610327565b50505092915050565b60006020828403121561021a57600080fd5b81356001604060020a0381111561023057600080fd5b61023c848285016101b4565b949350505050565b61024d81610315565b82525050565b600061025e82610311565b808452610272816020860160208601610333565b61027b81610363565b9093016020019392505050565b61024d81610321565b602080825281016102a28184610253565b9392505050565b604081016102b78285610288565b6102a26020830184610244565b6040518181016001604060020a03811182821017156102e257600080fd5b604052919050565b60006001604060020a0382111561030057600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b60ff1690565b82818337506000910152565b60005b8381101561034e578181015183820152602001610336565b8381111561035d576000848401525b50505050565b601f01601f1916905600a265627a7a7230582008b76108b6bf36a2766e799f617e47a5feab326e99d46ea5c5bcb8d7dfc682db6c6578706572696d656e74616cf50037", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x27 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0xBD27C22D DUP2 EQ PUSH2 0x2C JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x38 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x4C PUSH2 0x47 CALLDATASIZE PUSH1 0x4 PUSH2 0x208 JUMP JUMPDEST PUSH2 0x63 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x5A SWAP3 SWAP2 SWAP1 PUSH2 0x2A9 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x6F DUP4 PUSH2 0x78 JUMP JUMPDEST SWAP2 POP SWAP2 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 MLOAD PUSH1 0x15 EQ PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662032 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xF1 PUSH1 0x2 EXP PUSH2 0x1897 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0xF1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP3 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP2 POP PUSH2 0x11F DUP4 PUSH1 0x1 PUSH2 0x126 JUMP JUMPDEST SWAP1 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4C656E677468206D7573742062652067726561746572207468616E206F722065 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790191817 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x1A1 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0xE8 SWAP2 SWAP1 PUSH2 0x291 JUMP JUMPDEST POP POP ADD PUSH1 0x14 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x1C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x1D8 PUSH2 0x1D3 DUP3 PUSH2 0x2EA JUMP JUMPDEST PUSH2 0x2C4 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x1F4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1FF DUP4 DUP3 DUP5 PUSH2 0x327 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x21A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH2 0x230 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x23C DUP5 DUP3 DUP6 ADD PUSH2 0x1B4 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x315 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x25E DUP3 PUSH2 0x311 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x272 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x333 JUMP JUMPDEST PUSH2 0x27B DUP2 PUSH2 0x363 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH2 0x24D DUP2 PUSH2 0x321 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x2A2 DUP2 DUP5 PUSH2 0x253 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x2B7 DUP3 DUP6 PUSH2 0x288 JUMP JUMPDEST PUSH2 0x2A2 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x244 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x2E2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH2 0x300 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x34E JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x336 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x35D JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x1F NOT AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 ADDMOD 0xb7 PUSH2 0x8B6 0xbf CALLDATASIZE LOG2 PUSH23 0x6E799F617E47A5FEAB326E99D46EA5C5BCB8D7DFC682DB PUSH13 0x6578706572696D656E74616CF5 STOP CALLDATACOPY ", - "sourceMap": "709:592:0:-;;;;;;;;;-1:-1:-1;;;709:592:0;;;;;;;;;;;;;823:170;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;823:170:0;;;;;;;;;;;;;;;;;;;;;;;;;;;923:5;930:7;960:26;976:9;960:15;:26::i;:::-;953:33;;;;823:170;;;:::o;965:393:1:-;1074:13;1101;1160:9;:16;1180:2;1160:22;1196:29;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1196:29:1;;;1139:96;;;;;;;-1:-1:-1;;;;;1139:96:1;;;;;;;;;;;;;;;;;;;1261:9;1271:1;1261:12;;;;;;;;;;;;;;-1:-1:-1;;;1261:12:1;;;;;;1255:19;;-1:-1:-1;1292:25:1;1304:9;1315:1;1292:11;:25::i;:::-;1284:33;-1:-1:-1;965:393:1;;;:::o;2204:868:2:-;2325:14;2388:5;2396:2;2388:10;2376:1;:8;:22;;2440;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2440:22:2;;;2355:117;;;;;;;-1:-1:-1;;;;;2355:117:2;;;;;;;;;;-1:-1:-1;;2974:13:2;2719:2;2974:13;2968:20;-1:-1:-1;;;;;2964:69:2;;2204:868::o;6:440:-1:-;;100:4;88:17;;84:27;-1:-1;74:2;;125:1;122;115:12;74:2;162:6;149:20;184:64;199:48;240:6;199:48;;;184:64;;;175:73;;268:6;261:5;254:21;304:4;296:6;292:17;337:4;330:5;326:16;372:3;363:6;358:3;354:16;351:25;348:2;;;389:1;386;379:12;348:2;399:41;433:6;428:3;423;399:41;;;67:379;;;;;;;;454:345;;567:2;555:9;546:7;542:23;538:32;535:2;;;583:1;580;573:12;535:2;618:31;;-1:-1;;;;;658:30;;655:2;;;701:1;698;691:12;655:2;721:62;775:7;766:6;755:9;751:22;721:62;;;711:72;529:270;-1:-1;;;;529:270;806:110;879:31;904:5;879:31;;;874:3;867:44;861:55;;;923:292;;1021:35;1050:5;1021:35;;;1073:6;1068:3;1061:19;1085:63;1141:6;1134:4;1129:3;1125:14;1118:4;1111:5;1107:16;1085:63;;;1180:29;1202:6;1180:29;;;1160:50;;;1173:4;1160:50;;1001:214;-1:-1;;;1001:214;1222:104;1291:29;1314:5;1291:29;;1333:273;1457:2;1471:47;;;1442:18;;1532:64;1442:18;1582:6;1532:64;;;1524:72;1428:178;-1:-1;;;1428:178;1613:286;1745:2;1730:18;;1759:57;1734:9;1789:6;1759:57;;;1827:62;1885:2;1874:9;1870:18;1861:6;1827:62;;1906:256;1968:2;1962:9;1994:17;;;-1:-1;;;;;2054:34;;2090:22;;;2051:62;2048:2;;;2126:1;2123;2116:12;2048:2;2142;2135:22;1946:216;;-1:-1;1946:216;2169:258;;-1:-1;;;;;2304:6;2301:30;2298:2;;;2344:1;2341;2334:12;2298:2;-1:-1;2417:4;2388;2365:17;;;;-1:-1;;2361:33;2407:15;;2235:192;2434:88;2505:12;;2489:33;2529:128;-1:-1;;;;;2598:54;;2581:76;2664:88;2742:4;2731:16;;2714:38;2760:145;2841:6;2836:3;2831;2818:30;-1:-1;2897:1;2879:16;;2872:27;2811:94;2914:268;2979:1;2986:101;3000:6;2997:1;2994:13;2986:101;;;3067:11;;;3061:18;3048:11;;;3041:39;3022:2;3015:10;2986:101;;;3102:6;3099:1;3096:13;3093:2;;;3167:1;3158:6;3153:3;3149:16;3142:27;3093:2;2963:219;;;;;3190:97;3278:2;3258:14;-1:-1;;3254:28;;3238:49" + "object": "0x6080604052600436106100325763ffffffff60e060020a60003504166372c2f5278114610037578063bd27c22d14610070575b600080fd5b34801561004357600080fd5b5061005761005236600461058c565b61009e565b604051610067949392919061064a565b60405180910390f35b34801561007c57600080fd5b5061009061008b36600461058c565b6100bd565b60405161006792919061062f565b600080600060606100ae856100d2565b93509350935093509193509193565b6000806100c9836101b5565b91509150915091565b60008060006060603585511015606060405190810160405280602b81526020017f4d65746164617461206d75737420686176652061206c656e677468206f662061815260200160a960020a6a3a103632b0b9ba101a9997028152509015156101595760405160e560020a62461bcd028152600401610150919061061e565b60405180910390fd5b5084600081518110151561016957fe5b016020015160f860020a90819004810204935061018785600161025a565b92506101948560156102d6565b91506035855111156101ae576101ab8560356102e9565b90505b9193509193565b6000808251601514606060405190810160405280602281526020017f4d65746164617461206d75737420686176652061206c656e677468206f662032815260200160f160020a611897028152509015156102255760405160e560020a62461bcd028152600401610150919061061e565b5082600081518110151561023557fe5b016020015160f860020a90819004810204915061025383600161025a565b9050915091565b60008160140183511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a3790191817028152509015156102c35760405160e560020a62461bcd028152600401610150919061061e565b50500160140151600160a060020a031690565b60006102e28383610426565b9392505050565b606060008260200184511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a3790199917028152509015156103545760405160e560020a62461bcd028152600401610150919061061e565b5061035f84846102d6565b905080836020010184511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a3790199917028152509015156103ca5760405160e560020a62461bcd028152600401610150919061061e565b50806040519080825280601f01601f1916602001820160405280156103f9578160200160208202803883390190505b50915061041f61040883610499565b6020018461041587610499565b016020018361049c565b5092915050565b60008160200183511015606060405190810160405280602b8152602001600080516020610738833981519152815260200160a960020a6a38bab0b6103a37901999170281525090151561048f5760405160e560020a62461bcd028152600401610150919061061e565b5050016020015190565b90565b8015156104a857610533565b828214156104b557610533565b6020601f8201046020820660008111156104d0576001820391505b6000602083025b808210156104f25781860151828801526020820191506104d7565b600083111561052e578260200360080260020a8287015181828204028560080260020a858b0151818282020480841780898f0152505050505050505b505050505b505050565b6000601f8201831361054957600080fd5b813561055c610557826106b4565b61068e565b9150808252602083016020830185838301111561057857600080fd5b6105838382846106f1565b50505092915050565b60006020828403121561059e57600080fd5b81356001604060020a038111156105b457600080fd5b6105c084828501610538565b949350505050565b6105d1816106df565b82525050565b60006105e2826106db565b8084526105f68160208601602086016106fd565b6105ff8161072d565b9093016020019392505050565b6105d181610499565b6105d1816106eb565b602080825281016102e281846105d7565b6040810161063d8285610615565b6102e260208301846105c8565b608081016106588287610615565b61066560208301866105c8565b610672604083018561060c565b818103606083015261068481846105d7565b9695505050505050565b6040518181016001604060020a03811182821017156106ac57600080fd5b604052919050565b60006001604060020a038211156106ca57600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b60ff1690565b82818337506000910152565b60005b83811015610718578181015183820152602001610700565b83811115610727576000848401525b50505050565b601f01601f19169056004c656e677468206d7573742062652067726561746572207468616e206f722065a265627a7a723058205132eb7448f5b6279dedd3c042e96fb9ea0d8a8aea79044353638cf00546165f6c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x32 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x72C2F527 DUP2 EQ PUSH2 0x37 JUMPI DUP1 PUSH4 0xBD27C22D EQ PUSH2 0x70 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x43 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x57 PUSH2 0x52 CALLDATASIZE PUSH1 0x4 PUSH2 0x58C JUMP JUMPDEST PUSH2 0x9E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x67 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x64A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x7C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x90 PUSH2 0x8B CALLDATASIZE PUSH1 0x4 PUSH2 0x58C JUMP JUMPDEST PUSH2 0xBD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x67 SWAP3 SWAP2 SWAP1 PUSH2 0x62F JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 PUSH2 0xAE DUP6 PUSH2 0xD2 JUMP JUMPDEST SWAP4 POP SWAP4 POP SWAP4 POP SWAP4 POP SWAP2 SWAP4 POP SWAP2 SWAP4 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH2 0xC9 DUP4 PUSH2 0x1B5 JUMP JUMPDEST SWAP2 POP SWAP2 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 PUSH1 0x35 DUP6 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662061 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x3A103632B0B9BA101A9997 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x159 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP DUP5 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x169 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP4 POP PUSH2 0x187 DUP6 PUSH1 0x1 PUSH2 0x25A JUMP JUMPDEST SWAP3 POP PUSH2 0x194 DUP6 PUSH1 0x15 PUSH2 0x2D6 JUMP JUMPDEST SWAP2 POP PUSH1 0x35 DUP6 MLOAD GT ISZERO PUSH2 0x1AE JUMPI PUSH2 0x1AB DUP6 PUSH1 0x35 PUSH2 0x2E9 JUMP JUMPDEST SWAP1 POP JUMPDEST SWAP2 SWAP4 POP SWAP2 SWAP4 JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 MLOAD PUSH1 0x15 EQ PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4D65746164617461206D75737420686176652061206C656E677468206F662032 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xF1 PUSH1 0x2 EXP PUSH2 0x1897 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x225 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP DUP3 PUSH1 0x0 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x235 JUMPI INVALID JUMPDEST ADD PUSH1 0x20 ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV DUP2 MUL DIV SWAP2 POP PUSH2 0x253 DUP4 PUSH1 0x1 PUSH2 0x25A JUMP JUMPDEST SWAP1 POP SWAP2 POP SWAP2 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790191817 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x2C3 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP POP ADD PUSH1 0x14 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x2E2 DUP4 DUP4 PUSH2 0x426 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x0 DUP3 PUSH1 0x20 ADD DUP5 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790199917 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x354 JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP PUSH2 0x35F DUP5 DUP5 PUSH2 0x2D6 JUMP JUMPDEST SWAP1 POP DUP1 DUP4 PUSH1 0x20 ADD ADD DUP5 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790199917 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x3CA JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP DUP1 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x3F9 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP2 POP PUSH2 0x41F PUSH2 0x408 DUP4 PUSH2 0x499 JUMP JUMPDEST PUSH1 0x20 ADD DUP5 PUSH2 0x415 DUP8 PUSH2 0x499 JUMP JUMPDEST ADD PUSH1 0x20 ADD DUP4 PUSH2 0x49C JUMP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO PUSH1 0x60 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x2B DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x738 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0xA9 PUSH1 0x2 EXP PUSH11 0x38BAB0B6103A3790199917 MUL DUP2 MSTORE POP SWAP1 ISZERO ISZERO PUSH2 0x48F JUMPI PUSH1 0x40 MLOAD PUSH1 0xE5 PUSH1 0x2 EXP PUSH3 0x461BCD MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x150 SWAP2 SWAP1 PUSH2 0x61E JUMP JUMPDEST POP POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST DUP1 ISZERO ISZERO PUSH2 0x4A8 JUMPI PUSH2 0x533 JUMP JUMPDEST DUP3 DUP3 EQ ISZERO PUSH2 0x4B5 JUMPI PUSH2 0x533 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x1F DUP3 ADD DIV PUSH1 0x20 DUP3 MOD PUSH1 0x0 DUP2 GT ISZERO PUSH2 0x4D0 JUMPI PUSH1 0x1 DUP3 SUB SWAP2 POP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP4 MUL JUMPDEST DUP1 DUP3 LT ISZERO PUSH2 0x4F2 JUMPI DUP2 DUP7 ADD MLOAD DUP3 DUP9 ADD MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH2 0x4D7 JUMP JUMPDEST PUSH1 0x0 DUP4 GT ISZERO PUSH2 0x52E JUMPI DUP3 PUSH1 0x20 SUB PUSH1 0x8 MUL PUSH1 0x2 EXP DUP3 DUP8 ADD MLOAD DUP2 DUP3 DUP3 DIV MUL DUP6 PUSH1 0x8 MUL PUSH1 0x2 EXP DUP6 DUP12 ADD MLOAD DUP2 DUP3 DUP3 MUL DIV DUP1 DUP5 OR DUP1 DUP10 DUP16 ADD MSTORE POP POP POP POP POP POP POP JUMPDEST POP POP POP POP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x549 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x55C PUSH2 0x557 DUP3 PUSH2 0x6B4 JUMP JUMPDEST PUSH2 0x68E JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x578 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x583 DUP4 DUP3 DUP5 PUSH2 0x6F1 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x59E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH2 0x5B4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x5C0 DUP5 DUP3 DUP6 ADD PUSH2 0x538 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0x5D1 DUP2 PUSH2 0x6DF JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5E2 DUP3 PUSH2 0x6DB JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x5F6 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x6FD JUMP JUMPDEST PUSH2 0x5FF DUP2 PUSH2 0x72D JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH2 0x5D1 DUP2 PUSH2 0x499 JUMP JUMPDEST PUSH2 0x5D1 DUP2 PUSH2 0x6EB JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x2E2 DUP2 DUP5 PUSH2 0x5D7 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x63D DUP3 DUP6 PUSH2 0x615 JUMP JUMPDEST PUSH2 0x2E2 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x5C8 JUMP JUMPDEST PUSH1 0x80 DUP2 ADD PUSH2 0x658 DUP3 DUP8 PUSH2 0x615 JUMP JUMPDEST PUSH2 0x665 PUSH1 0x20 DUP4 ADD DUP7 PUSH2 0x5C8 JUMP JUMPDEST PUSH2 0x672 PUSH1 0x40 DUP4 ADD DUP6 PUSH2 0x60C JUMP JUMPDEST DUP2 DUP2 SUB PUSH1 0x60 DUP4 ADD MSTORE PUSH2 0x684 DUP2 DUP5 PUSH2 0x5D7 JUMP JUMPDEST SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x6AC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH2 0x6CA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x718 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x700 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x727 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x1F NOT AND SWAP1 JUMP STOP 0x4c PUSH6 0x6E677468206D PUSH22 0x73742062652067726561746572207468616E206F7220 PUSH6 0xA265627A7A72 ADDRESS PC KECCAK256 MLOAD ORIGIN 0xeb PUSH21 0x48F5B6279DEDD3C042E96FB9EA0D8A8AEA79044353 PUSH4 0x8CF00546 AND 0x5f PUSH13 0x6578706572696D656E74616CF5 STOP CALLDATACOPY ", + "sourceMap": "709:590:0:-;;;;;;;;;-1:-1:-1;;;709:590:0;;;;;;;;;;;;;;;;;;1044:253;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;1044:253:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;823:170;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;823:170:0;;;;;;;;;;;;;;;;;;1044:253;1158:5;1177:7;1198;1219:5;1263:27;1280:9;1263:16;:27::i;:::-;1256:34;;;;;;;;1044:253;;;;;:::o;823:170::-;923:5;930:7;960:26;976:9;960:15;:26::i;:::-;953:33;;;;823:170;;;:::o;1409:608:1:-;1519:13;1546;1573:15;1602:17;1685:2;1665:9;:16;:22;;1701:30;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1701:30:1;;;1644:97;;;;;;;-1:-1:-1;;;;;1644:97:1;;;;;;;;;;;;;;;;;;;1767:9;1777:1;1767:12;;;;;;;;;;;;;;-1:-1:-1;;;1767:12:1;;;;;;1761:19;;-1:-1:-1;1798:25:1;1810:9;1821:1;1798:11;:25::i;:::-;1790:33;;1843:26;1855:9;1866:2;1843:11;:26::i;:::-;1833:36;;1902:2;1883:9;:16;:21;1879:83;;;1927:24;1937:9;1948:2;1927:9;:24::i;:::-;1920:31;;1879:83;1409:608;;;;;:::o;965:393::-;1074:13;1101;1160:9;:16;1180:2;1160:22;1196:29;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1196:29:1;;;1139:96;;;;;;;-1:-1:-1;;;;;1139:96:1;;;;;;;;;;;1261:9;1271:1;1261:12;;;;;;;;;;;;;;-1:-1:-1;;;1261:12:1;;;;;;1255:19;;-1:-1:-1;1292:25:1;1304:9;1315:1;1292:11;:25::i;:::-;1284:33;-1:-1:-1;965:393:1;;;:::o;2204:868:2:-;2325:14;2388:5;2396:2;2388:10;2376:1;:8;:22;;2440;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2440:22:2;;;;-1:-1:-1;;;;;2440:22:2;;;2355:117;;;;;;;-1:-1:-1;;;;;2355:117:2;;;;;;;;;;-1:-1:-1;;2974:13:2;2719:2;2974:13;2968:20;-1:-1:-1;;;;;2964:69:2;;2204:868::o;6338:195::-;6459:14;6504:21;6516:1;6519:5;6504:11;:21::i;:::-;6496:30;6338:195;-1:-1:-1;;;6338:195:2:o;7192:869::-;7311:19;7484:25;7418:5;7426:2;7418:10;7406:1;:8;:22;;7442;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7442:22:2;;;;-1:-1:-1;;;;;7442:22:2;;;7385:89;;;;;;;-1:-1:-1;;;;;7385:89:2;;;;;;;;;;;7512:21;7524:1;7527:5;7512:11;:21::i;:::-;7484:49;;7672:17;7659:5;7667:2;7659:10;:30;7647:1;:8;:42;;7703:22;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7703:22:2;;;;-1:-1:-1;;;;;7703:22:2;;;7626:109;;;;;;;-1:-1:-1;;;;;7626:109:2;;;;;;;;;;;7817:17;7807:28;;;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;7807:28:2;;7798:37;;7845:185;7865:21;7879:6;7865:13;:21::i;:::-;7889:2;7865:26;7953:5;7934:16;7948:1;7934:13;:16::i;:::-;:24;7961:2;7934:29;8003:17;7845:6;:185::i;:::-;7192:869;;;;;:::o;4956:472::-;5077:14;5140:5;5148:2;5140:10;5128:1;:8;:22;;5164;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;5164:22:2;;;;-1:-1:-1;;;;;5164:22:2;;;5107:89;;;;;;;-1:-1:-1;;;;;5107:89:2;;;;;;;;;;-1:-1:-1;;5375:13:2;5277:2;5375:13;5369:20;;4956:472::o;629:203:3:-;786:5;629:203::o;961:3173::-;1122:11;;1119:23;;;1135:7;;1119:23;1164:4;1154:6;:14;1151:26;;;1170:7;;1151:26;1369:4;1362;1354:6;1350:17;1346:28;1416:4;1408:6;1404:17;1451:1;1440:9;1437:16;1434:2;;;1506:1;1492:12;1488:20;1472:36;;1434:2;1601:1;1636:4;1632:23;;1668:156;1697:9;1689:6;1686:21;1668:156;;;1801:6;1793;1789:19;1783:26;1773:6;1767:4;1763:17;1756:54;1731:4;1723:6;1719:17;1709:27;;1668:156;;;1891:1;1880:9;1877:16;1874:2;;;2492:9;2486:4;2482:20;2479:1;2475:28;2472:1;2468:36;2557:6;2549;2545:19;2539:26;2641:17;2621;2609:10;2605:34;2601:58;3349:9;3346:1;3342:17;3339:1;3335:25;3409:6;3403:4;3399:17;3393:24;3487:15;3469;3459:8;3455:30;3451:52;3980:9;3967:11;3964:26;4087:16;4078:6;4072:4;4068:17;4061:43;1894:2224;;;;;;;1874:2;1238:2890;;;;;;;;:::o;6:440:-1:-;;100:4;88:17;;84:27;-1:-1;74:2;;125:1;122;115:12;74:2;162:6;149:20;184:64;199:48;240:6;199:48;;;184:64;;;175:73;;268:6;261:5;254:21;304:4;296:6;292:17;337:4;330:5;326:16;372:3;363:6;358:3;354:16;351:25;348:2;;;389:1;386;379:12;348:2;399:41;433:6;428:3;423;399:41;;;67:379;;;;;;;;454:345;;567:2;555:9;546:7;542:23;538:32;535:2;;;583:1;580;573:12;535:2;618:31;;-1:-1;;;;;658:30;;655:2;;;701:1;698;691:12;655:2;721:62;775:7;766:6;755:9;751:22;721:62;;;711:72;529:270;-1:-1;;;;529:270;806:110;879:31;904:5;879:31;;;874:3;867:44;861:55;;;923:297;;1023:38;1055:5;1023:38;;;1078:6;1073:3;1066:19;1090:63;1146:6;1139:4;1134:3;1130:14;1123:4;1116:5;1112:16;1090:63;;;1185:29;1207:6;1185:29;;;1165:50;;;1178:4;1165:50;;1003:217;-1:-1;;;1003:217;1526:110;1599:31;1624:5;1599:31;;1643:104;1712:29;1735:5;1712:29;;1754:273;1878:2;1892:47;;;1863:18;;1953:64;1863:18;2003:6;1953:64;;2034:286;2166:2;2151:18;;2180:57;2155:9;2210:6;2180:57;;;2248:62;2306:2;2295:9;2291:18;2282:6;2248:62;;2327:573;2533:3;2518:19;;2548:57;2522:9;2578:6;2548:57;;;2616:62;2674:2;2663:9;2659:18;2650:6;2616:62;;;2689;2747:2;2736:9;2732:18;2723:6;2689:62;;;2799:9;2793:4;2789:20;2784:2;2773:9;2769:18;2762:48;2824:66;2885:4;2876:6;2824:66;;;2816:74;2504:396;-1:-1;;;;;;2504:396;2907:256;2969:2;2963:9;2995:17;;;-1:-1;;;;;3055:34;;3091:22;;;3052:62;3049:2;;;3127:1;3124;3117:12;3049:2;3143;3136:22;2947:216;;-1:-1;2947:216;3170:258;;-1:-1;;;;;3305:6;3302:30;3299:2;;;3345:1;3342;3335:12;3299:2;-1:-1;3418:4;3389;3366:17;;;;-1:-1;;3362:33;3408:15;;3236:192;3435:91;3509:12;;3493:33;3628:128;-1:-1;;;;;3697:54;;3680:76;3849:88;3927:4;3916:16;;3899:38;3945:145;4026:6;4021:3;4016;4003:30;-1:-1;4082:1;4064:16;;4057:27;3996:94;4099:268;4164:1;4171:101;4185:6;4182:1;4179:13;4171:101;;;4252:11;;;4246:18;4233:11;;;4226:39;4207:2;4200:10;4171:101;;;4287:6;4284:1;4281:13;4278:2;;;4352:1;4343:6;4338:3;4334:16;4327:27;4278:2;4148:219;;;;;4375:97;4463:2;4443:14;-1:-1;;4439:28;;4423:49" } } }, @@ -57,12 +88,12 @@ } }, "sourceCodes": { - "current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol\";\n\ncontract TestLibAssetProxyDecoder is\n LibAssetProxyDecoder\n{\n\n /// @dev Decodes ERC721 Asset Proxy data\n function publicDecodeERC20Data(bytes memory proxyData)\n public\n pure\n returns (uint8, address)\n {\n return decodeERC20Data(proxyData);\n }\n\n /// @dev Decodes ERC721 Asset Proxy data\n function publicDecodeERC721Data(bytes memory proxyData)\n internal\n pure\n returns (\n uint8,\n address,\n uint256,\n bytes memory\n )\n {\n return decodeERC721Data(proxyData);\n }\n}\n", + "current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol\";\n\ncontract TestLibAssetProxyDecoder is\n LibAssetProxyDecoder\n{\n\n /// @dev Decodes ERC721 Asset Proxy data\n function publicDecodeERC20Data(bytes memory proxyData)\n public\n pure\n returns (uint8, address)\n {\n return decodeERC20Data(proxyData);\n }\n\n /// @dev Decodes ERC721 Asset Proxy data\n function publicDecodeERC721Data(bytes memory proxyData)\n public\n pure\n returns (\n uint8,\n address,\n uint256,\n bytes memory\n )\n {\n return decodeERC721Data(proxyData);\n }\n}\n", "current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"../LibBytes/LibBytes.sol\";\n\ncontract LibAssetProxyDecoder is\n LibBytes\n{\n\n string constant INVALID_ERC20_METADATA_LENGTH = \"Metadata must have a length of 21.\";\n string constant INVALID_ERC721_METADATA_LENGTH = \"Metadata must have a length of at least 53.\";\n\n /// @dev Decodes ERC721 Asset Proxy data\n function decodeERC20Data(bytes memory proxyData)\n internal\n pure\n returns (\n uint8 proxyId,\n address token\n )\n {\n require(\n proxyData.length == 21,\n INVALID_ERC20_METADATA_LENGTH\n );\n proxyId = uint8(proxyData[0]);\n token = readAddress(proxyData, 1);\n\n return (proxyId, token);\n }\n\n /// @dev Decodes ERC721 Asset Proxy data\n function decodeERC721Data(bytes memory proxyData)\n internal\n pure\n returns (\n uint8 proxyId,\n address token,\n uint256 tokenId,\n bytes memory data\n )\n {\n require(\n proxyData.length >= 53,\n INVALID_ERC721_METADATA_LENGTH\n );\n proxyId = uint8(proxyData[0]);\n token = readAddress(proxyData, 1);\n tokenId = readUint256(proxyData, 21);\n if (proxyData.length > 53) {\n data = readBytes(proxyData, 53);\n }\n\n return (proxyId, token, tokenId, data);\n }\n}\n", "current/utils/LibBytes/LibBytes.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\n\nimport \"../LibMem/LibMem.sol\";\n\ncontract LibBytes is\n LibMem\n{\n\n // Revert reasons\n string constant GTE_20_LENGTH_REQUIRED = \"Length must be greater than or equal to 20.\";\n string constant GTE_32_LENGTH_REQUIRED = \"Length must be greater than or equal to 32.\";\n\n /// @dev Tests equality of two byte arrays.\n /// @param lhs First byte array to compare.\n /// @param rhs Second byte array to compare.\n /// @return True if arrays are the same. False otherwise.\n function areBytesEqual(bytes memory lhs, bytes memory rhs)\n internal\n pure\n returns (bool equal)\n {\n assembly {\n // Get the number of words occupied by \n let lenFullWords := div(add(mload(lhs), 0x1F), 0x20)\n\n // Add 1 to the number of words, to account for the length field\n lenFullWords := add(lenFullWords, 0x1)\n\n // Test equality word-by-word.\n // Terminates early if there is a mismatch.\n for {let i := 0} lt(i, lenFullWords) {i := add(i, 1)} {\n let lhsWord := mload(add(lhs, mul(i, 0x20)))\n let rhsWord := mload(add(rhs, mul(i, 0x20)))\n equal := eq(lhsWord, rhsWord)\n if eq(equal, 0) {\n // Break\n i := lenFullWords\n }\n }\n }\n\n return equal;\n }\n\n /// @dev Reads an address from a position in a byte array.\n /// @param b Byte array containing an address.\n /// @param index Index in byte array of address.\n /// @return address from byte array.\n function readAddress(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (address result)\n {\n require(\n b.length >= index + 20, // 20 is length of address\n GTE_20_LENGTH_REQUIRED\n );\n\n // Add offset to index:\n // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)\n // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)\n index += 20;\n\n // Read address from array memory\n assembly {\n // 1. Add index to address of bytes array\n // 2. Load 32-byte word from memory\n // 3. Apply 20-byte mask to obtain address\n result := and(mload(add(b, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n }\n return result;\n }\n\n /// @dev Writes an address into a specific position in a byte array.\n /// @param b Byte array to insert address into.\n /// @param index Index in byte array of address.\n /// @param input Address to put into byte array.\n function writeAddress(\n bytes memory b,\n uint256 index,\n address input\n )\n internal\n pure\n {\n require(\n b.length >= index + 20, // 20 is length of address\n GTE_20_LENGTH_REQUIRED\n );\n\n // Add offset to index:\n // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)\n // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)\n index += 20;\n\n // Store address into array memory\n assembly {\n // The address occupies 20 bytes and mstore stores 32 bytes.\n // First fetch the 32-byte word where we'll be storing the address, then\n // apply a mask so we have only the bytes in the word that the address will not occupy.\n // Then combine these bytes with the address and store the 32 bytes back to memory with mstore.\n\n // 1. Add index to address of bytes array\n // 2. Load 32-byte word from memory\n // 3. Apply 12-byte mask to obtain extra bytes occupying word of memory where we'll store the address\n let neighbors := and(mload(add(b, index)), 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)\n\n // Store the neighbors and address into memory\n mstore(add(b, index), xor(input, neighbors))\n }\n }\n\n /// @dev Reads a bytes32 value from a position in a byte array.\n /// @param b Byte array containing a bytes32 value.\n /// @param index Index in byte array of bytes32 value.\n /// @return bytes32 value from byte array.\n function readBytes32(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (bytes32 result)\n {\n require(\n b.length >= index + 32,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Arrays are prefixed by a 256 bit length parameter\n index += 32;\n\n // Read the bytes32 from array memory\n assembly {\n result := mload(add(b, index))\n }\n return result;\n }\n\n /// @dev Writes a bytes32 into a specific position in a byte array.\n /// @param b Byte array to insert into.\n /// @param index Index in byte array of .\n /// @param input bytes32 to put into byte array.\n function writeBytes32(\n bytes memory b,\n uint256 index,\n bytes32 input\n )\n internal\n pure\n {\n require(\n b.length >= index + 32,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Arrays are prefixed by a 256 bit length parameter\n index += 32;\n\n // Read the bytes32 from array memory\n assembly {\n mstore(add(b, index), input)\n }\n }\n\n /// @dev Reads a uint256 value from a position in a byte array.\n /// @param b Byte array containing a uint256 value.\n /// @param index Index in byte array of uint256 value.\n /// @return uint256 value from byte array.\n function readUint256(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (uint256 result)\n {\n return uint256(readBytes32(b, index));\n }\n\n /// @dev Writes a uint256 into a specific position in a byte array.\n /// @param b Byte array to insert into.\n /// @param index Index in byte array of .\n /// @param input uint256 to put into byte array.\n function writeUint256(\n bytes memory b,\n uint256 index,\n uint256 input\n )\n internal\n pure\n {\n writeBytes32(b, index, bytes32(input));\n }\n\n /// @dev Reads a uint256 value from a position in a byte array.\n /// @param b Byte array containing a uint256 value.\n /// @param index Index in byte array of uint256 value.\n /// @return uint256 value from byte array.\n function readBytes(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (bytes memory result)\n {\n // Read length of nested bytes\n require(\n b.length >= index + 32,\n GTE_32_LENGTH_REQUIRED\n );\n uint256 nestedBytesLength = readUint256(b, index);\n\n // Assert length of is valid, given\n // length of nested bytes\n require(\n b.length >= index + 32 + nestedBytesLength,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Allocate memory and copy value to result\n result = new bytes(nestedBytesLength);\n memcpy(\n getMemAddress(result) + 32, // +32 skips array length\n getMemAddress(b) + index + 32, // +32 skips array length\n nestedBytesLength\n );\n\n return result;\n }\n\n /// @dev Writes a uint256 into a specific position in a byte array.\n /// @param b Byte array to insert into.\n /// @param index Index in byte array of .\n /// @param input uint256 to put into byte array.\n function writeBytes(\n bytes memory b,\n uint256 index,\n bytes memory input\n )\n internal\n pure\n {\n // Read length of nested bytes\n require(\n b.length >= index + 32 /* 32 bytes to store length */ + input.length,\n GTE_32_LENGTH_REQUIRED\n );\n\n // Copy into \n memcpy(\n getMemAddress(b) + index,\n getMemAddress(input),\n input.length + 32 /* 32 bytes to store length */\n );\n }\n}\n", "current/utils/LibMem/LibMem.sol": "/*\n\n Copyright 2018 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 solidity ^0.4.24;\n\ncontract LibMem {\n\n function getMemAddress(bytes memory input)\n internal\n pure\n returns (uint256 address_)\n {\n assembly {\n address_ := input\n }\n return address_;\n }\n\n /// @dev Writes a uint256 into a specific position in a byte array.\n /// @param dest memory adress to copy bytes to\n function memcpy(\n uint256 dest,\n uint256 source,\n uint256 length\n )\n internal\n pure\n {\n // Base cases\n if(length == 0) return;\n if(source == dest) return;\n\n // Copy bytes from source to dest\n assembly {\n // Compute number of complete words to copy + remaining bytes\n let lenFullWords := div(add(length, 0x1F), 0x20)\n let remainder := mod(length, 0x20)\n if gt(remainder, 0) {\n lenFullWords := sub(lenFullWords, 1)\n }\n\n // Copy full words from source to dest\n let offset := 0\n let maxOffset := mul(0x20, lenFullWords)\n for {offset := 0} lt(offset, maxOffset) {offset := add(offset, 0x20)} {\n mstore(add(dest, offset), mload(add(source, offset)))\n }\n\n // Copy remaining bytes\n if gt(remainder, 0) {\n // Read a full word from source, containing X bytes to copy to dest.\n // We only want to keep the X bytes, zeroing out the remaining bytes.\n // We accomplish this by a right shift followed by a left shift.\n // Example:\n // Suppose a word of 8 bits has all 1's: [11111111]\n // Let X = 7 (we want to copy the first 7 bits)\n // Apply a right shift of 1: [01111111]\n // Apply a left shift of 1: [11111110]\n let sourceShiftFactor := exp(2, mul(8, sub(0x20, remainder)))\n let sourceWord := mload(add(source, offset))\n let sourceBytes := mul(div(sourceWord, sourceShiftFactor), sourceShiftFactor)\n\n // Read a full word from dest, containing (32-X) bytes to retain.\n // We need to zero out the remaining bytes to be overwritten by source,\n // while retaining the (32-X) bytes we don't want to overwrite.\n // We accomplish this by a left shift followed by a right shift.\n // Example:\n // Suppose a word of 8 bits has all 1's: [11111111]\n // Let X = 7 (we want to free the first 7 bits, and retain the last bit)\n // Apply a left shift of 1: [11111110]\n // Apply a right shift of 1: [01111111]\n let destShiftFactor := exp(2, mul(8, remainder))\n let destWord := mload(add(dest, offset))\n let destBytes := div(mul(destWord, destShiftFactor), destShiftFactor)\n\n // Combine the source and dest bytes. There should be no overlap:\n // The source bytes run from [0..X-1] and the dest bytes from [X..31].\n // Example:\n // Following the example from above, we have [11111110]\n // from the source word and [01111111] from the dest word.\n // Combine these words using to get [11111111].\n let combinedDestWord := or(sourceBytes, destBytes)\n\n // Store the combined word into dest\n mstore(add(dest, offset), combinedDestWord)\n }\n }\n }\n}\n" }, - "sourceTreeHashHex": "0x8431fff2ae9424603c06a10d9c4649edf92a798a8969fe69339fc0063b7ad144", + "sourceTreeHashHex": "0x872ca57a3559c6ce5cd050e72e3b25fdfc98cb222b1835d097ee16dc444c1733", "compiler": { "name": "solc", "version": "0.4.24", -- cgit v1.2.3 From d9f9895b2bcd3cde09febbe0e1af31be5ddc80e2 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 24 May 2018 16:44:37 -0700 Subject: Test for onReceived erc721 callback --- packages/contracts/compiler.json | 2 +- packages/contracts/package.json | 2 +- packages/contracts/src/utils/artifacts.ts | 2 + packages/contracts/src/utils/types.ts | 1 + packages/contracts/test/asset_proxy/decoder.ts | 2 +- packages/contracts/test/asset_proxy/proxies.ts | 122 ++++++++++++++++++++++++- 6 files changed, 126 insertions(+), 5 deletions(-) diff --git a/packages/contracts/compiler.json b/packages/contracts/compiler.json index 639849cd7..464137d9b 100644 --- a/packages/contracts/compiler.json +++ b/packages/contracts/compiler.json @@ -21,8 +21,8 @@ "contracts": [ "AssetProxyOwner", "DummyERC20Token", - "DummyERC721Token", "DummyERC721Receiver", + "DummyERC721Token", "ERC20Proxy", "ERC721Proxy", "Exchange", diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 43c33e7d3..658f5ed60 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -30,7 +30,7 @@ "test:circleci": "yarn test" }, "config": { - "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibAssetProxyDecoder|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" + "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|DummyERC721Receiver|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibAssetProxyDecoder|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" }, "repository": { "type": "git", diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index 44de43a95..a1c8483d8 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -2,6 +2,7 @@ import { ContractArtifact } from '@0xproject/sol-compiler'; import * as AssetProxyOwner from '../artifacts/AssetProxyOwner.json'; import * as DummyERC20Token from '../artifacts/DummyERC20Token.json'; +import * as DummyERC721Receiver from '../artifacts/DummyERC721Receiver.json'; import * as DummyERC721Token from '../artifacts/DummyERC721Token.json'; import * as ERC20Proxy from '../artifacts/ERC20Proxy.json'; import * as ERC721Proxy from '../artifacts/ERC721Proxy.json'; @@ -23,6 +24,7 @@ import * as ZRX from '../artifacts/ZRXToken.json'; export const artifacts = { AssetProxyOwner: (AssetProxyOwner as any) as ContractArtifact, DummyERC20Token: (DummyERC20Token as any) as ContractArtifact, + DummyERC721Receiver: (DummyERC721Receiver as any) as ContractArtifact, DummyERC721Token: (DummyERC721Token as any) as ContractArtifact, ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 70abb2643..cccca5705 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -97,6 +97,7 @@ export enum ContractName { TestSignatureValidator = 'TestSignatureValidator', ERC20Proxy = 'ERC20Proxy', ERC721Proxy = 'ERC721Proxy', + DummyERC721Receiver = 'DummyERC721Receiver', DummyERC721Token = 'DummyERC721Token', TestLibBytes = 'TestLibBytes', Authorizable = 'Authorizable', diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index b35cd0d43..4416334d1 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -19,7 +19,7 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -describe.only('LibAssetProxyDecoder', () => { +describe('LibAssetProxyDecoder', () => { let owner: string; let testAssetProxyDecoder: TestLibAssetProxyDecoderContract; let testAddress: string; diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index d14280c5f..d7f27deb4 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -1,25 +1,37 @@ +import { LogWithDecodedArgs, ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { assetProxyUtils } from '@0xproject/order-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; +import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; +import { + DummyERC721ReceiverContract, + TokenReceivedContractEventArgs, +} from '../../src/contract_wrappers/generated/dummy_e_r_c721_receiver'; import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token'; import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy'; import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy'; +import { artifacts } from '../../src/utils/artifacts'; import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions'; +import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC721Wrapper } from '../../src/utils/erc721_wrapper'; -import { provider, web3Wrapper } from '../../src/utils/web3_wrapper'; +import { LogDecoder } from '../../src/utils/log_decoder'; +import { AssetProxyId } from '../../src/utils/types'; +import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('Asset Transfer Proxies', () => { + const nullDataHex = '0x'; + let owner: string; let notAuthorized: string; let exchangeAddress: string; @@ -28,6 +40,7 @@ describe('Asset Transfer Proxies', () => { let zrxToken: DummyERC20TokenContract; let erc721Token: DummyERC721TokenContract; + let erc721Receiver: DummyERC721ReceiverContract; let erc20Proxy: ERC20ProxyContract; let erc721Proxy: ERC721ProxyContract; @@ -69,6 +82,20 @@ describe('Asset Transfer Proxies', () => { }), constants.AWAIT_TRANSACTION_MINED_MS, ); + + await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, { + from: owner, + }); + + erc721Receiver = await DummyERC721ReceiverContract.deployFrom0xArtifactAsync( + artifacts.DummyERC721Receiver, + provider, + txDefaults, + ); + + zeroEx = new ZeroEx(provider, { + networkId: constants.TESTRPC_NETWORK_ID, + }); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -234,7 +261,7 @@ describe('Asset Transfer Proxies', () => { }); }); - describe('Transfer Proxy - ERC721', () => { + describe.only('Transfer Proxy - ERC721', () => { describe('transferFrom', () => { it('should successfully transfer tokens', async () => { // Construct metadata for ERC721 proxy @@ -262,6 +289,97 @@ describe('Asset Transfer Proxies', () => { expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress); }); + it.only('should call onERC721Received when transferring to a smart contract', async () => { + // Construct metadata for ERC721 proxy + const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( + erc721Token.address, + erc721MakerTokenId, + ); + // Verify pre-condition + const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); + // Perform a transfer from makerAddress to takerAddress + const erc20Balances = await erc20Wrapper.getBalancesAsync(); + const amount = new BigNumber(1); + const txHash = await erc721Proxy.transferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + erc721Receiver.address, + amount, + { from: exchangeAddress }, + ); + // Parse transaction logs + const tx = await zeroEx.awaitTransactionMinedAsync(txHash); + tx.logs = _.filter(tx.logs, log => log.address === erc721Receiver.address); + const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); + tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log)); + // Validate log emitted by erc721 receiver + expect(tx.logs.length).to.be.equal(1); + const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs; + expect(tokenReceivedLog.args.from).to.be.equal(makerAddress); + expect(tokenReceivedLog.args.tokenId).to.be.bignumber.equal(erc721MakerTokenId); + expect(tokenReceivedLog.args.data).to.be.equal(nullDataHex); + // Verify transfer was successful + const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address); + }); + + it('should call onERC721Received when transferring to a smart contract and receive extra data', async () => { + // Construct metadata for ERC721 proxy + const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( + erc721Token.address, + erc721MakerTokenId, + ); + // Verify pre-condition + const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); + // Perform a transfer from makerAddress to takerAddress + const erc20Balances = await erc20Wrapper.getBalancesAsync(); + const amount = new BigNumber(1); + const txHash = await erc721Proxy.transferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + erc721Receiver.address, + amount, + { from: exchangeAddress }, + ); + // Parse transaction logs + const tx = await zeroEx.awaitTransactionMinedAsync(txHash); + tx.logs = _.filter(tx.logs, log => log.address === erc721Receiver.address); + const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); + tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log)); + // Verify erc721 receiver log emitted + console.log(tx.logs); + // Verify transfer was successful + const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address); + }); + + /* + it('should throw if receiving contract does not have onERC721Received', async () => { + // Construct metadata for ERC721 proxy + const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( + erc721Token.address, + erc721MakerTokenId, + ); + // Verify pre-condition + const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); + // Perform a transfer from makerAddress to takerAddress + const erc20Balances = await erc20Wrapper.getBalancesAsync(); + const amount = new BigNumber(1); + await erc721Proxy.transferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + takerAddress, + amount, + { from: exchangeAddress }, + ); + // Verify transfer was successful + const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress); + });*/ + it('should throw if transferring 0 amount of a token', async () => { // Construct metadata for ERC721 proxy const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( -- cgit v1.2.3 From 842363200b3b8aded3b03fc8e46a329ff9534e36 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 25 May 2018 00:31:03 -0700 Subject: Tons of tests around nested byte arrays and ERC721 receiver --- .../current/test/TestLibBytes/TestLibBytes.sol | 25 +++++ .../contracts/current/utils/LibBytes/LibBytes.sol | 17 ++- packages/contracts/test/asset_proxy/decoder.ts | 26 ++++- packages/contracts/test/asset_proxy/proxies.ts | 36 +++--- packages/contracts/test/libraries/lib_bytes.ts | 121 ++++++++++++++++++++- packages/order-utils/src/asset_proxy_utils.ts | 30 ++++- 6 files changed, 223 insertions(+), 32 deletions(-) diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 69554605d..0bf11b03b 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -155,6 +155,7 @@ contract TestLibBytes is return b; } +======= /// @dev Reads the first 4 bytes from a byte array of arbitrary length. /// @param b Byte array to read first 4 bytes from. /// @return First 4 bytes of data. @@ -166,4 +167,28 @@ contract TestLibBytes is result = readFirst4(b); return result; } + + function publicReadBytes( + bytes memory b, + uint256 index) + public + pure + returns (bytes memory result) + { + result = readBytes(b, index); + return result; + } + + + function publicWriteBytes( + bytes memory b, + uint256 index, + bytes memory input) + public + pure + returns (bytes memory) + { + writeBytes(b, index, input); + return b; + } } diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index fb8359462..6351f1a46 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -300,24 +300,21 @@ contract LibBytes is returns (bytes memory result) { // Read length of nested bytes - require( - b.length >= index + 32, - GTE_32_LENGTH_REQUIRED - ); uint256 nestedBytesLength = readUint256(b, index); + index += 32; // Assert length of is valid, given // length of nested bytes require( - b.length >= index + 32 + nestedBytesLength, + b.length >= index + nestedBytesLength, GTE_32_LENGTH_REQUIRED ); // Allocate memory and copy value to result result = new bytes(nestedBytesLength); memcpy( - getMemAddress(result) + 32, // +32 skips array length - getMemAddress(b) + index + 32, // +32 skips array length + getMemAddress(result) + 32, // +32 skips array length + getMemAddress(b) + index + 32, nestedBytesLength ); @@ -344,9 +341,9 @@ contract LibBytes is // Copy into memcpy( - getMemAddress(b) + index, - getMemAddress(input), - input.length + 32 /* 32 bytes to store length */ + getMemAddress(b) + index + 32, // +32 to skip length of + getMemAddress(input), // include length of byte array + input.length + 32 // +32 bytes to store length ); } } diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 4416334d1..0f1413ff1 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -56,21 +56,45 @@ describe('LibAssetProxyDecoder', () => { expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); }); - it('should correctly decode ERC721 proxy data)', async () => { + it('should correctly decode ERC721 proxy data', async () => { const tokenId = ZeroEx.generatePseudoRandomSalt(); const encodedProxyData = assetProxyUtils.encodeERC721ProxyData(testAddress, tokenId); const expectedDecodedProxyData = assetProxyUtils.decodeERC721ProxyData(encodedProxyData); let decodedAssetProxyId: number; let decodedTokenAddress: string; let decodedTokenId: BigNumber; + let decodedData: string; [ decodedAssetProxyId, decodedTokenAddress, decodedTokenId, + decodedData, ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedProxyData); expect(decodedAssetProxyId).to.be.equal(expectedDecodedProxyData.assetProxyId); expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedProxyData.tokenId); + expect(decodedData).to.be.equal(expectedDecodedProxyData.data); + }); + + it('should correctly decode ERC721 proxy data with receiver data', async () => { + const tokenId = ZeroEx.generatePseudoRandomSalt(); + const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())) + 'FFFF'; + const encodedProxyData = assetProxyUtils.encodeERC721ProxyData(testAddress, tokenId, data); + const expectedDecodedProxyData = assetProxyUtils.decodeERC721ProxyData(encodedProxyData); + let decodedAssetProxyId: number; + let decodedTokenAddress: string; + let decodedTokenId: BigNumber; + let decodedData: string; + [ + decodedAssetProxyId, + decodedTokenAddress, + decodedTokenId, + decodedData, + ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedProxyData); + expect(decodedAssetProxyId).to.be.equal(expectedDecodedProxyData.assetProxyId); + expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); + expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedProxyData.tokenId); + expect(decodedData).to.be.equal(expectedDecodedProxyData.data); }); }); }); diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index d7f27deb4..4995e95a0 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -261,7 +261,7 @@ describe('Asset Transfer Proxies', () => { }); }); - describe.only('Transfer Proxy - ERC721', () => { + describe('Transfer Proxy - ERC721', () => { describe('transferFrom', () => { it('should successfully transfer tokens', async () => { // Construct metadata for ERC721 proxy @@ -289,7 +289,7 @@ describe('Asset Transfer Proxies', () => { expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress); }); - it.only('should call onERC721Received when transferring to a smart contract', async () => { + it('should call onERC721Received when transferring to a smart contract', async () => { // Construct metadata for ERC721 proxy const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( erc721Token.address, @@ -326,9 +326,11 @@ describe('Asset Transfer Proxies', () => { it('should call onERC721Received when transferring to a smart contract and receive extra data', async () => { // Construct metadata for ERC721 proxy + const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( erc721Token.address, erc721MakerTokenId, + data, ); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -348,14 +350,17 @@ describe('Asset Transfer Proxies', () => { tx.logs = _.filter(tx.logs, log => log.address === erc721Receiver.address); const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log)); - // Verify erc721 receiver log emitted - console.log(tx.logs); + // Validate log emitted by erc721 receiver + expect(tx.logs.length).to.be.equal(1); + const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs; + expect(tokenReceivedLog.args.from).to.be.equal(makerAddress); + expect(tokenReceivedLog.args.tokenId).to.be.bignumber.equal(erc721MakerTokenId); + expect(tokenReceivedLog.args.data).to.be.equal(data); // Verify transfer was successful const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address); }); - /* it('should throw if receiving contract does not have onERC721Received', async () => { // Construct metadata for ERC721 proxy const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( @@ -368,17 +373,16 @@ describe('Asset Transfer Proxies', () => { // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); - await erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, - makerAddress, - takerAddress, - amount, - { from: exchangeAddress }, - ); - // Verify transfer was successful - const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); - expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress); - });*/ + return expect( + erc721Proxy.transferFrom.sendTransactionAsync( + encodedProxyMetadata, + makerAddress, + erc20Proxy.address, // the ERC20 proxy does not have an ERC721 receiver + amount, + { from: exchangeAddress }, + ), + ).to.be.rejectedWith(constants.REVERT); + }); it('should throw if transferring 0 amount of a token', async () => { // Construct metadata for ERC721 proxy diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 0996cdc84..a6e3c7d37 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -6,7 +6,8 @@ import ethUtil = require('ethereumjs-util'); import { TestLibBytesContract } from '../../src/generated_contract_wrappers/test_lib_bytes'; import { artifacts } from '../../src/utils/artifacts'; -import { expectRevertOrOtherErrorAsync } from '../../src/utils/assertions'; +import { expectRevertOrOtherErrorAsync, expectRevertOrOtherErrorAsync } from '../../src/utils/assertions'; +import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; @@ -28,6 +29,15 @@ describe('LibBytes', () => { let testAddress: string; const testBytes32 = '0x102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f01020'; const testUint256 = new BigNumber(testBytes32, 16); + let shortData: string; + let shortTestBytes: string; + let shortTestBytesAsBuffer: Buffer; + let wordOfData: string; + let wordOfTestBytes: string; + let wordOfTestBytesAsBuffer: Buffer; + let longData: string; + let longTestBytes: string; + let longTestBytesAsBuffer: Buffer; before(async () => { await blockchainLifecycle.startAsync(); @@ -48,6 +58,26 @@ describe('LibBytes', () => { expect(byteArrayLongerThan32BytesLength).to.be.greaterThan(32); const testBytes32Length = ethUtil.toBuffer(testBytes32).byteLength; expect(testBytes32Length).to.be.equal(32); + // Create short test bytes + shortData = '0xffffaa'; + const encodedShortData = ethUtil.toBuffer(shortData); + const shortDataLength = new BigNumber(encodedShortData.byteLength); + const encodedShortDataLength = assetProxyUtils.encodeUint256(shortDataLength); + shortTestBytesAsBuffer = Buffer.concat([encodedShortDataLength, encodedShortData]); + shortTestBytes = ethUtil.bufferToHex(shortTestBytesAsBuffer); + // Create test bytes one word in length + wordOfData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); + const encodedWordOfData = ethUtil.toBuffer(wordOfData); + const wordOfDataLength = new BigNumber(encodedWordOfData.byteLength); + const encodedWordOfDataLength = assetProxyUtils.encodeUint256(wordOfDataLength); + wordOfTestBytesAsBuffer = Buffer.concat([encodedWordOfDataLength, encodedWordOfData]); + wordOfTestBytes = ethUtil.bufferToHex(wordOfTestBytesAsBuffer); + // Create long test bytes (combines short test bytes with word of test bytes) + longData = ethUtil.bufferToHex(Buffer.concat([encodedShortData, encodedWordOfData])); + const longDataLength = new BigNumber(encodedShortData.byteLength + encodedWordOfData.byteLength); + const encodedLongDataLength = assetProxyUtils.encodeUint256(longDataLength); + longTestBytesAsBuffer = Buffer.concat([encodedLongDataLength, encodedShortData, encodedWordOfData]); + longTestBytes = ethUtil.bufferToHex(longTestBytesAsBuffer); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -285,6 +315,7 @@ describe('LibBytes', () => { }); */ +======= describe('readFirst4', () => { // AssertionError: expected promise to be rejected with an error including 'revert' but it was fulfilled with '0x08c379a0' it('should revert if byte array has a length < 4', async () => { @@ -300,4 +331,92 @@ describe('LibBytes', () => { expect(first4Bytes).to.equal(expectedFirst4Bytes); }); }); + + describe('readBytes', () => { + it('should successfully read short, nested array of bytes when it takes up the whole array', async () => { + const testBytesOffset = new BigNumber(0); + const bytes = await libBytes.publicReadBytes.callAsync(shortTestBytes, testBytesOffset); + return expect(bytes).to.be.equal(shortData); + }); + + it('should successfully read short, nested array of bytes when it is offset in the array', async () => { + const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); + const shortDataAsBuffer = ethUtil.toBuffer(shortData); + const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, shortTestBytesAsBuffer]); + const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); + const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); + const bytes = await libBytes.publicReadBytes.callAsync(combinedByteArray, testUint256Offset); + return expect(bytes).to.be.equal(shortData); + }); + + it('should successfully read a nested array of bytes - one word in length - when it takes up the whole array', async () => { + const testBytesOffset = new BigNumber(0); + const bytes = await libBytes.publicReadBytes.callAsync(wordOfTestBytes, testBytesOffset); + return expect(bytes).to.be.equal(wordOfData); + }); + + it('should successfully read a nested array of bytes - one word in length - when it is offset in the array', async () => { + const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); + const wordOfDataAsBuffer = ethUtil.toBuffer(wordOfData); + const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, wordOfTestBytesAsBuffer]); + const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); + const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); + const bytes = await libBytes.publicReadBytes.callAsync(combinedByteArray, testUint256Offset); + return expect(bytes).to.be.equal(wordOfData); + }); + + it('should successfully read long, nested array of bytes when it takes up the whole array', async () => { + const testBytesOffset = new BigNumber(0); + const bytes = await libBytes.publicReadBytes.callAsync(longTestBytes, testBytesOffset); + return expect(bytes).to.be.equal(longData); + }); + + it('should successfully read long, nested array of bytes when it is offset in the array', async () => { + const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); + const longDataAsBuffer = ethUtil.toBuffer(longData); + const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, longTestBytesAsBuffer]); + const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); + const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); + const bytes = await libBytes.publicReadBytes.callAsync(combinedByteArray, testUint256Offset); + return expect(bytes).to.be.equal(longData); + }); + + it('should fail if the byte array is too short to hold the length of a nested byte array)', async () => { + // The length of the nested array is 32 bytes. By storing less than 32 bytes, a length cannot be read. + const offset = new BigNumber(0); + return expect(libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( + constants.REVERT, + ); + }); + + it('should fail if we store a nested byte array length, without a nested byte array)', async () => { + const offset = new BigNumber(0); + return expect(libBytes.publicReadBytes.callAsync(testBytes32, offset)).to.be.rejectedWith(constants.REVERT); + }); + + it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => { + const badOffset = new BigNumber(ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength); + return expect( + libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, badOffset), + ).to.be.rejectedWith(constants.REVERT); + }); + + it('should fail if the length between the offset and end of the byte array is too short to hold the nested byte array)', async () => { + const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); + return expect(libBytes.publicReadBytes.callAsync(testBytes32, badOffset)).to.be.rejectedWith( + constants.REVERT, + ); + }); + }); + + /// @TODO Implement test cases for writeUint256. Test template below. + /// Currently, the generated contract wrappers do not support this library's write methods. + /* + describe('writeBytes', () => { + it('should successfully write bytes when it takes up the whole array)', async () => {}); + it('should successfully write bytes when it is offset in the array)', async () => {}); + it('should fail if the byte array is too short to hold the nested bytes)', async () => {}); + it('should fail if the length between the offset and end of the byte array is too short to hold the nested bytes)', async () => {}); + }); + */ }); diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index 55f2d56df..8255376a1 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -2,6 +2,7 @@ import { AssetProxyId, ERC20ProxyData, ERC721ProxyData, ProxyData } from '@0xpro import { BigNumber } from '@0xproject/utils'; import BN = require('bn.js'); import ethUtil = require('ethereumjs-util'); +import * as _ from 'lodash'; const ERC20_PROXY_METADATA_BYTE_LENGTH = 21; const ERC721_PROXY_METADATA_BYTE_LENGTH = 53; @@ -74,19 +75,25 @@ export const assetProxyUtils = { }; return erc20ProxyData; }, - encodeERC721ProxyData(tokenAddress: string, tokenId: BigNumber): string { + encodeERC721ProxyData(tokenAddress: string, tokenId: BigNumber, data?: string): string { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC721); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); const encodedTokenId = assetProxyUtils.encodeUint256(tokenId); const encodedMetadata = Buffer.concat([encodedAddress, encodedTokenId, encodedAssetProxyId]); + if (!_.isUndefined(data)) { + const encodedData = ethUtil.toBuffer(data); + const dataLength = new BigNumber(encodedData.byteLength); + const encodedDataLength = assetProxyUtils.encodeUint256(dataLength); + encodedMetadata = Buffer.concat([encodedMetadata, encodedDataLength, encodedData]); + } const encodedMetadataHex = ethUtil.bufferToHex(encodedMetadata); return encodedMetadataHex; }, decodeERC721ProxyData(proxyData: string): ERC721ProxyData { const encodedProxyMetadata = ethUtil.toBuffer(proxyData); - if (encodedProxyMetadata.byteLength !== ERC721_PROXY_METADATA_BYTE_LENGTH) { + if (encodedProxyMetadata.byteLength < ERC721_PROXY_METADATA_BYTE_LENGTH) { throw new Error( - `Could not decode ERC20 Proxy Data. Expected length of encoded data to be 53. Got ${ + `Could not decode ERC20 Proxy Data. Expected length of encoded data to be at least 53. Got ${ encodedProxyMetadata.byteLength }`, ); @@ -106,10 +113,25 @@ export const assetProxyUtils = { const tokenIdOffset = ERC721_PROXY_METADATA_BYTE_LENGTH - 1; const encodedTokenId = encodedProxyMetadata.slice(addressOffset, tokenIdOffset); const tokenId = assetProxyUtils.decodeUint256(encodedTokenId); - const erc721ProxyData = { + const nullData = '0x'; + let data = nullData; + if (encodedProxyMetadata.byteLength > 53) { + const encodedDataLength = encodedProxyMetadata.slice(53, 85); + const dataLength = assetProxyUtils.decodeUint256(encodedDataLength); + const expectedDataLength = new BigNumber(encodedProxyMetadata.byteLength - 85); + if (!dataLength.equals(expectedDataLength)) { + throw new Error( + `Data length (${dataLength}) does not match actual length of data (${expectedDataLength})`, + ); + } + const encodedData = encodedProxyMetadata.slice(85); + data = ethUtil.bufferToHex(encodedData); + } + const erc721ProxyData: ERC721ProxyData = { assetProxyId, tokenAddress, tokenId, + data, }; return erc721ProxyData; }, -- cgit v1.2.3 From d17e031259e11e3e37cbb837245171cbdd4d219b Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 25 May 2018 17:20:00 -0700 Subject: Fixed up wording in memcpy --- packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol index b07a5da54..215a661e2 100644 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -82,8 +82,8 @@ contract LibMem { // Example: // Suppose a word of 8 bits has all 1's: [11111111] // Let X = 7 (we want to free the first 7 bits, and retain the last bit) - // Apply a left shift of 1: [11111110] - // Apply a right shift of 1: [01111111] + // Apply a left shift of 7: [10000000] + // Apply a right shift of 7: [00000001] let destShiftFactor := exp(2, mul(8, remainder)) let destWord := mload(add(dest, offset)) let destBytes := div(mul(destWord, destShiftFactor), destShiftFactor) @@ -92,7 +92,7 @@ contract LibMem { // The source bytes run from [0..X-1] and the dest bytes from [X..31]. // Example: // Following the example from above, we have [11111110] - // from the source word and [01111111] from the dest word. + // from the source word and [00000001] from the dest word. // Combine these words using to get [11111111]. let combinedDestWord := or(sourceBytes, destBytes) -- cgit v1.2.3 From b3c253ea2a685bea3add43a81229911269eb4e89 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 25 May 2018 18:19:25 -0700 Subject: Tests for writing bytes to nested bytes --- packages/contracts/test/libraries/lib_bytes.ts | 100 ++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 9 deletions(-) diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index a6e3c7d37..cd5fdcf17 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -409,14 +409,96 @@ describe('LibBytes', () => { }); }); - /// @TODO Implement test cases for writeUint256. Test template below. - /// Currently, the generated contract wrappers do not support this library's write methods. - /* - describe('writeBytes', () => { - it('should successfully write bytes when it takes up the whole array)', async () => {}); - it('should successfully write bytes when it is offset in the array)', async () => {}); - it('should fail if the byte array is too short to hold the nested bytes)', async () => {}); - it('should fail if the length between the offset and end of the byte array is too short to hold the nested bytes)', async () => {}); + describe.only('writeBytes', () => { + it('should successfully write short, nested array of bytes when it takes up the whole array)', async () => { + const testBytesOffset = new BigNumber(0); + const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength)); + const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, shortData); + const bytesRead = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset); + return expect(bytesRead).to.be.equal(shortData); + }); + + it('should successfully write short, nested array of bytes when it is offset in the array', async () => { + // Write a prefix to the array + const prefixData = '0xabcdef'; + const prefixDataAsBuffer = ethUtil.toBuffer(prefixData); + const prefixOffset = new BigNumber(0); + const emptyByteArray = ethUtil.bufferToHex( + new Buffer(prefixDataAsBuffer.byteLength + shortTestBytesAsBuffer.byteLength), + ); + let bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, prefixOffset, prefixData); + // Write data after prefix + const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength); + bytesWritten = await libBytes.publicWriteBytes.callAsync(bytesWritten, testBytesOffset, shortData); + // Read data after prefix and validate + const bytes = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset); + return expect(bytes).to.be.equal(shortData); + }); + + it('should successfully write a nested array of bytes - one word in length - when it takes up the whole array)', async () => { + const testBytesOffset = new BigNumber(0); + const emptyByteArray = ethUtil.bufferToHex(new Buffer(wordOfTestBytesAsBuffer.byteLength)); + const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, wordOfData); + const bytesRead = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset); + return expect(bytesRead).to.be.equal(wordOfData); + }); + + it('should successfully write a nested array of bytes - one word in length - when it is offset in the array', async () => { + // Write a prefix to the array + const prefixData = '0xabcdef'; + const prefixDataAsBuffer = ethUtil.toBuffer(prefixData); + const prefixOffset = new BigNumber(0); + const emptyByteArray = ethUtil.bufferToHex( + new Buffer(prefixDataAsBuffer.byteLength + wordOfTestBytesAsBuffer.byteLength), + ); + let bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, prefixOffset, prefixData); + // Write data after prefix + const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength); + bytesWritten = await libBytes.publicWriteBytes.callAsync(bytesWritten, testBytesOffset, wordOfData); + // Read data after prefix and validate + const bytes = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset); + return expect(bytes).to.be.equal(wordOfData); + }); + + it('should successfully write a long, nested bytes when it takes up the whole array)', async () => { + const testBytesOffset = new BigNumber(0); + const emptyByteArray = ethUtil.bufferToHex(new Buffer(longTestBytesAsBuffer.byteLength)); + const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, longData); + const bytesRead = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset); + return expect(bytesRead).to.be.equal(longData); + }); + + it('should successfully write long, nested array of bytes when it is offset in the array', async () => { + // Write a prefix to the array + const prefixData = '0xabcdef'; + const prefixDataAsBuffer = ethUtil.toBuffer(prefixData); + const prefixOffset = new BigNumber(0); + const emptyByteArray = ethUtil.bufferToHex( + new Buffer(prefixDataAsBuffer.byteLength + longTestBytesAsBuffer.byteLength), + ); + let bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, prefixOffset, prefixData); + // Write data after prefix + const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength); + bytesWritten = await libBytes.publicWriteBytes.callAsync(bytesWritten, testBytesOffset, longData); + // Read data after prefix and validate + const bytes = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset); + return expect(bytes).to.be.equal(longData); + }); + + it('should fail if the byte array is too short to hold the length of a nested byte array)', async () => { + const offset = new BigNumber(0); + const emptyByteArray = ethUtil.bufferToHex(new Buffer(1)); + return expect(libBytes.publicWriteBytes.callAsync(emptyByteArray, offset, longData)).to.be.rejectedWith( + constants.REVERT, + ); + }); + + it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => { + const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength)); + const badOffset = new BigNumber(ethUtil.toBuffer(shortTestBytesAsBuffer).byteLength); + return expect(libBytes.publicWriteBytes.callAsync(emptyByteArray, badOffset, shortData)).to.be.rejectedWith( + constants.REVERT, + ); + }); }); - */ }); -- cgit v1.2.3 From f5bc0b205c217eac8abdfee9dcdb3c4d21b5c31e Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 28 May 2018 12:50:03 +0200 Subject: Generate tests from vectors --- .../current/test/TestLibMem/TestLibMem.sol | 27 ++++++++++++-- packages/contracts/test/libraries/lib_mem.ts | 42 ++++++++++++++++++++-- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol index 0c6f8fbc9..18deede4c 100644 --- a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol +++ b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol @@ -19,12 +19,33 @@ pragma solidity ^0.4.24; import "../../utils/LibMem/LibMem.sol"; -import "../../utils/LibBytes/LibBytes.sol"; contract TestLibMem is - LibMem, - LibBytes + LibMem { + function testMemcpy( + bytes mem, ///< Memory contents we want to apply memcpy to + uint256 dest, + uint256 source, + uint256 length + ) + public // not external, we need input in memory + pure + returns (bytes) + { + // Sanity check. Overflows are not checked. + require(source + length <= mem.length); + require(dest + length <= mem.length); + + // Get pointer to memory contents + uint256 offset = getMemAddress(mem) + 32; + + // Execute memcpy adjusted for memory array location + memcpy(offset + dest, offset + source, length); + + // Return modified memory contents + return mem; + } function test1() external diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 6ce4ab9b6..c884d5fea 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -18,6 +18,14 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +// BUG: Ideally we would use Buffer.from(memory).toString('hex') +// https://github.com/Microsoft/TypeScript/issues/23155 +const toHex = (buf: Uint8Array): string => + buf.reduce((a, v) => a + ('00' + v.toString(16)).slice(-2), '0x'); + +const fromHex = (str: string): Uint8Array => + Uint8Array.from(Buffer.from(str.slice(2), 'hex')); + describe('LibMem', () => { let owner: string; let testLibMem: TestLibMemContract; @@ -36,7 +44,37 @@ describe('LibMem', () => { await blockchainLifecycle.revertAsync(); }); - describe('LibMem', () => { + describe('memcpy', () => { + + // Create memory 0x000102...FF + const memSize = 256; + const memory = (new Uint8Array(memSize)).map((_, i) => i); + const memHex = toHex(memory); + + // Reference implementation to test against + const refMemcpy = (mem: Uint8Array, dest: number, source: number, length: number): Uint8Array => + Uint8Array.from(memory).copyWithin(dest, source, source + length); + + // Test vectors: destination, source, length, job description + const tests: Array<[number, number, number, string]> = [ + [1, 5, 4, 'four bytes within one word'], + ]; + + // Construct test cases + tests.forEach(([dest, source, length, job]) => + it(`copies ${job}`, async () => { + const expected = refMemcpy(memory, dest, source, length); + const resultStr = await testLibMem.testMemcpy.callAsync( + memHex, + new BigNumber(dest), + new BigNumber(source), + new BigNumber(length), + ); + const result = fromHex(resultStr); + expect(result).to.deep.equal(expected); + }), + ); + it('should )', async () => { await testLibMem.test1.sendTransactionAsync(); }); @@ -62,7 +100,7 @@ describe('LibMem', () => { }); it('should )', async () => { - return expect(testLibMem.test7.sendTransactionAsync()).to.be.rejectedWith(constants.REVERT); + return expect(testLibMem.test7.sendTransactionAsync()).to.be.rejectedWith(constants.REVERT ); }); }); }); -- cgit v1.2.3 From 76b918d40e3bb485cdd45149888f012d9ec2b67f Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 28 May 2018 13:07:04 +0200 Subject: Convert Solidity tests to vectors --- .../current/test/TestLibMem/TestLibMem.sol | 203 --------------------- packages/contracts/test/libraries/lib_mem.ts | 35 +--- 2 files changed, 6 insertions(+), 232 deletions(-) diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol index 18deede4c..64bc182f4 100644 --- a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol +++ b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol @@ -46,207 +46,4 @@ contract TestLibMem is // Return modified memory contents return mem; } - - function test1() - external - { - // Length of array & length to copy - uint256 length = 0; - - // Create source array - bytes memory sourceArray = new bytes(length); - - // Create dest array with same contents as source array - bytes memory destArray = new bytes(length); - memcpy( - getMemAddress(destArray) + 32, // skip copying array length - getMemAddress(sourceArray) + 32, // skip copying array length - length - ); - - // Verify contents of source & dest arrays match - require( - areBytesEqual(sourceArray, destArray), - "Test #1 failed. Array contents are not the same." - ); - } - - function test2() - external - { - // Length of array & length to copy - uint256 length = 1; - - // Create source array - bytes memory sourceArray = new bytes(length); - sourceArray[0] = byte(1); - - // Create dest array with same contents as source array - bytes memory destArray = new bytes(length); - memcpy( - getMemAddress(destArray) + 32, // skip copying array length - getMemAddress(sourceArray) + 32, // skip copying array length - length - ); - - // Verify contents of source & dest arrays match - require( - areBytesEqual(sourceArray, destArray), - "Test #2 failed. Array contents are not the same." - ); - } - - function test3() - external - { - // Length of array & length to copy - uint256 length = 11; - - // Create source array - bytes memory sourceArray = new bytes(length); - for(uint256 i = 0; i < length; ++i) { - sourceArray[i] = byte((i % 0xF) + 1); // [1..f] - } - - // Create dest array with same contents as source array - bytes memory destArray = new bytes(length); - memcpy( - getMemAddress(destArray) + 32, // skip copying array length - getMemAddress(sourceArray) + 32, // skip copying array length - length - ); - - // Verify contents of source & dest arrays match - require( - areBytesEqual(sourceArray, destArray), - "Test #3 failed. Array contents are not the same." - ); - } - - function test4() - external - { - // Length of array & length to copy - uint256 length = 32; - - // Create source array - bytes memory sourceArray = new bytes(length); - for(uint256 i = 0; i < length; ++i) { - sourceArray[i] = byte((i % 0xF) + 1); // [1..f] - } - - // Create dest array with same contents as source array - bytes memory destArray = new bytes(length); - memcpy( - getMemAddress(destArray) + 32, // skip copying array length - getMemAddress(sourceArray) + 32, // skip copying array length - length - ); - - // Verify contents of source & dest arrays match - require( - areBytesEqual(sourceArray, destArray), - "Test #4 failed. Array contents are not the same." - ); - } - - function test5() - external - { - // Length of array & length to copy - uint256 length = 72; - - // Create source array - bytes memory sourceArray = new bytes(length); - for(uint256 i = 0; i < length; ++i) { - sourceArray[i] = byte((i % 0xF) + 1); // [1..f] - } - - // Create dest array with same contents as source array - bytes memory destArray = new bytes(length); - memcpy( - getMemAddress(destArray) + 32, // skip copying array length - getMemAddress(sourceArray) + 32, // skip copying array length - length - ); - - // Verify contents of source & dest arrays match - require( - areBytesEqual(sourceArray, destArray), - "Test #5 failed. Array contents are not the same." - ); - } - - - function test6() - external - { - // Length of arrays - uint256 length1 = 72; - uint256 length2 = 100; - - // The full source array is used for comparisons at the end - bytes memory fullSourceArray = new bytes(length1 + length2); - - // First source array - bytes memory sourceArray1 = new bytes(length1); - for(uint256 i = 0; i < length1; ++i) { - sourceArray1[i] = byte((i % 0xF) + 1); // [1..f] - fullSourceArray[i] = byte((i % 0xF) + 1); // [1..f] - } - - // Second source array - bytes memory sourceArray2 = new bytes(length2); - for(uint256 j = 0; i < length2; ++i) { - sourceArray2[j] = byte((j % 0xF) + 1); // [1..f] - fullSourceArray[length1+j] = byte((j % 0xF) + 1); // [1..f] - } - - // Create dest array with same contents as source arrays - bytes memory destArray = new bytes(length1 + length2); - memcpy( - getMemAddress(destArray) + 32, // skip copying array length - getMemAddress(sourceArray1) + 32, // skip copying array length - length1 - ); - memcpy( - getMemAddress(destArray) + 32 + length1, // skip copying array length + sourceArray1 bytes - getMemAddress(sourceArray2) + 32, // skip copying array length - length2 - ); - - // Verify contents of source & dest arrays match - require( - areBytesEqual(fullSourceArray, destArray), - "Test #6 failed. Array contents are not the same." - ); - } - - function test7() - external - { - // Length of array & length to copy - uint256 length = 72; - - // Create source array - bytes memory sourceArray = new bytes(length); - for(uint256 i = 0; i < length; ++i) { - sourceArray[i] = byte((i % 0xF) + 1); // [1..f] - } - - // Create dest array with same contents as source array - bytes memory destArray = new bytes(length); - memcpy( - getMemAddress(destArray) + 32, // skip copying array length - getMemAddress(sourceArray) + 32, // skip copying array length - length - 8 // Copy all but last byte. - ); - - // Verify contents of source & dest arrays match - // We expect this to fail - require( - areBytesEqual(sourceArray, destArray), - "Test #7 failed. Array contents are not the same. This is expected." - ); - } } diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index c884d5fea..24f933ad8 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -57,7 +57,12 @@ describe('LibMem', () => { // Test vectors: destination, source, length, job description const tests: Array<[number, number, number, string]> = [ - [1, 5, 4, 'four bytes within one word'], + [128, 0, 0, 'zero bytes'], + [128, 0, 1, 'one byte'], + [128, 0, 11, 'eleven bytes'], + [128, 0, 32, 'one word'], + [128, 0, 72, 'two words and eight bytes'], + [128, 0, 100, 'three words and four bytes'] ]; // Construct test cases @@ -74,33 +79,5 @@ describe('LibMem', () => { expect(result).to.deep.equal(expected); }), ); - - it('should )', async () => { - await testLibMem.test1.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test2.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test3.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test4.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test5.sendTransactionAsync(); - }); - - it('should )', async () => { - await testLibMem.test6.sendTransactionAsync(); - }); - - it('should )', async () => { - return expect(testLibMem.test7.sendTransactionAsync()).to.be.rejectedWith(constants.REVERT ); - }); }); }); -- cgit v1.2.3 From 27351c9a902b945b7507e5c76e77dcc7cae855f8 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 28 May 2018 13:16:05 +0200 Subject: Cleanup test script --- packages/contracts/test/libraries/lib_mem.ts | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 24f933ad8..8658a89b0 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -1,22 +1,13 @@ -import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js'; -import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import BN = require('bn.js'); import * as chai from 'chai'; -import ethUtil = require('ethereumjs-util'); -import * as Web3 from 'web3'; import { TestLibMemContract } from '../../src/contract_wrappers/generated/test_lib_mem'; import { artifacts } from '../../src/utils/artifacts'; import { chaiSetup } from '../../src/utils/chai_setup'; -import { constants } from '../../src/utils/constants'; -import { AssetProxyId } from '../../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); // BUG: Ideally we would use Buffer.from(memory).toString('hex') // https://github.com/Microsoft/TypeScript/issues/23155 @@ -37,12 +28,6 @@ describe('LibMem', () => { // Deploy TestLibMem testLibMem = await TestLibMemContract.deployFrom0xArtifactAsync(artifacts.TestLibMem, provider, txDefaults); }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); describe('memcpy', () => { @@ -62,7 +47,7 @@ describe('LibMem', () => { [128, 0, 11, 'eleven bytes'], [128, 0, 32, 'one word'], [128, 0, 72, 'two words and eight bytes'], - [128, 0, 100, 'three words and four bytes'] + [128, 0, 100, 'three words and four bytes'], ]; // Construct test cases -- cgit v1.2.3 From 7f218725106947066713a1f9610f0550abb464fa Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 28 May 2018 13:55:26 +0200 Subject: Add test cases --- packages/contracts/test/libraries/lib_mem.ts | 150 ++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 17 deletions(-) diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 8658a89b0..4316bab6e 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -41,28 +41,144 @@ describe('LibMem', () => { Uint8Array.from(memory).copyWithin(dest, source, source + length); // Test vectors: destination, source, length, job description - const tests: Array<[number, number, number, string]> = [ + type Tests = Array<[number, number, number, string]>; + + const test = (tests: Tests) => + tests.forEach(([dest, source, length, job]) => + it(job, async () => { + const expected = refMemcpy(memory, dest, source, length); + const resultStr = await testLibMem.testMemcpy.callAsync( + memHex, + new BigNumber(dest), + new BigNumber(source), + new BigNumber(length), + ); + const result = fromHex(resultStr); + expect(result).to.deep.equal(expected); + }), + ); + + describe('copies forward', () => test([ [128, 0, 0, 'zero bytes'], [128, 0, 1, 'one byte'], [128, 0, 11, 'eleven bytes'], + [128, 0, 31, 'thirty-one bytes'], [128, 0, 32, 'one word'], + [128, 0, 33, 'one word and one byte'], [128, 0, 72, 'two words and eight bytes'], [128, 0, 100, 'three words and four bytes'], - ]; - - // Construct test cases - tests.forEach(([dest, source, length, job]) => - it(`copies ${job}`, async () => { - const expected = refMemcpy(memory, dest, source, length); - const resultStr = await testLibMem.testMemcpy.callAsync( - memHex, - new BigNumber(dest), - new BigNumber(source), - new BigNumber(length), - ); - const result = fromHex(resultStr); - expect(result).to.deep.equal(expected); - }), - ); + ])); + + describe('copies forward within one word', () => test([ + [16, 0, 0, 'zero bytes'], + [16, 0, 1, 'one byte'], + [16, 0, 11, 'eleven bytes'], + [16, 0, 16, 'sixteen bytes'], + ])); + + describe('copies forward with one byte overlap', () => test([ + [0, 0, 1, 'one byte'], + [10, 0, 11, 'eleven bytes'], + [30, 0, 31, 'thirty-one bytes'], + [31, 0, 32, 'one word'], + [32, 0, 33, 'one word and one byte'], + [71, 0, 72, 'two words and eight bytes'], + [99, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with thirty-one bytes overlap', () => test([ + [0, 0, 31, 'thirty-one bytes'], + [1, 0, 32, 'one word'], + [2, 0, 33, 'one word and one byte'], + [41, 0, 72, 'two words and eight bytes'], + [69, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with one word overlap', () => test([ + [0, 0, 32, 'one word'], + [1, 0, 33, 'one word and one byte'], + [41, 0, 72, 'two words and eight bytes'], + [69, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with one word and one byte overlap', () => test([ + [0, 0, 33, 'one word and one byte'], + [40, 0, 72, 'two words and eight bytes'], + [68, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with two words overlap', () => test([ + [0, 0, 64, 'two words'], + [8, 0, 72, 'two words and eight bytes'], + [36, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward within one word and one byte overlap', () => test([ + [0, 0, 1, 'one byte'], + [10, 0, 11, 'eleven bytes'], + [15, 0, 16, 'sixteen bytes'], + ])); + + describe('copies backward', () => test([ + [0, 128, 0, 'zero bytes'], + [0, 128, 1, 'one byte'], + [0, 128, 11, 'eleven bytes'], + [0, 128, 31, 'thirty-one bytes'], + [0, 128, 32, 'one word'], + [0, 128, 33, 'one word and one byte'], + [0, 128, 72, 'two words and eight bytes'], + [0, 128, 100, 'three words and four bytes'], + ])); + + describe('copies backward within one word', () => test([ + [0, 16, 0, 'zero bytes'], + [0, 16, 1, 'one byte'], + [0, 16, 11, 'eleven bytes'], + [0, 16, 16, 'sixteen bytes'], + ])); + + describe('copies backward with one byte overlap', () => test([ + [0, 0, 1, 'one byte'], + [0, 10, 11, 'eleven bytes'], + [0, 30, 31, 'thirty-one bytes'], + [0, 31, 32, 'one word'], + [0, 32, 33, 'one word and one byte'], + [0, 71, 72, 'two words and eight bytes'], + [0, 99, 100, 'three words and four bytes'], + ])); + + describe('copies backward with thirty-one bytes overlap', () => test([ + [0, 0, 31, 'thirty-one bytes'], + [0, 1, 32, 'one word'], + [0, 2, 33, 'one word and one byte'], + [0, 41, 72, 'two words and eight bytes'], + [0, 69, 100, 'three words and four bytes'], + ])); + + describe('copies backward with one word overlap', () => test([ + [0, 0, 32, 'one word'], + [0, 1, 33, 'one word and one byte'], + [0, 41, 72, 'two words and eight bytes'], + [0, 69, 100, 'three words and four bytes'], + ])); + + describe('copies backward with one word and one byte overlap', () => test([ + [0, 0, 33, 'one word and one byte'], + [0, 40, 72, 'two words and eight bytes'], + [0, 68, 100, 'three words and four bytes'], + ])); + + describe('copies backward with two words overlap', () => test([ + [0, 0, 64, 'two words'], + [0, 8, 72, 'two words and eight bytes'], + [0, 36, 100, 'three words and four bytes'], + ])); + + describe('copies forward within one word and one byte overlap', () => test([ + [0, 0, 1, 'one byte'], + [0, 10, 11, 'eleven bytes'], + [0, 15, 16, 'sixteen bytes'], + ])); + }); }); -- cgit v1.2.3 From 31e21db5b5c40a80b71bb411149bec3345cf17de Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 28 May 2018 14:13:39 +0200 Subject: Add test for zero-size overlap --- packages/contracts/test/libraries/lib_mem.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 4316bab6e..0a2f69f61 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -57,7 +57,9 @@ describe('LibMem', () => { expect(result).to.deep.equal(expected); }), ); - + + test([[0, 0, 0, 'copies zero bytes with overlap']]); + describe('copies forward', () => test([ [128, 0, 0, 'zero bytes'], [128, 0, 1, 'one byte'], -- cgit v1.2.3 From 63014aeb6bdd3fb92452ebe69f08d9dcbbe2b502 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 28 May 2018 14:29:12 +0200 Subject: Add tests for word loop iteration --- packages/contracts/test/libraries/lib_mem.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 0a2f69f61..225a8d60d 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -57,15 +57,17 @@ describe('LibMem', () => { expect(result).to.deep.equal(expected); }), ); - + test([[0, 0, 0, 'copies zero bytes with overlap']]); - + describe('copies forward', () => test([ [128, 0, 0, 'zero bytes'], [128, 0, 1, 'one byte'], [128, 0, 11, 'eleven bytes'], [128, 0, 31, 'thirty-one bytes'], [128, 0, 32, 'one word'], + [128, 0, 64, 'two words'], + [128, 0, 96, 'three words'], [128, 0, 33, 'one word and one byte'], [128, 0, 72, 'two words and eight bytes'], [128, 0, 100, 'three words and four bytes'], @@ -127,6 +129,8 @@ describe('LibMem', () => { [0, 128, 11, 'eleven bytes'], [0, 128, 31, 'thirty-one bytes'], [0, 128, 32, 'one word'], + [0, 128, 64, 'two words'], + [0, 128, 96, 'three words'], [0, 128, 33, 'one word and one byte'], [0, 128, 72, 'two words and eight bytes'], [0, 128, 100, 'three words and four bytes'], -- cgit v1.2.3 From 069b89b2084a65e6846a0722a9883af1104feb08 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Mon, 28 May 2018 15:24:09 +0200 Subject: Implement memcpy using masking and end-aligned words --- .../src/contracts/current/utils/LibMem/LibMem.sol | 144 ++++++++++++--------- 1 file changed, 85 insertions(+), 59 deletions(-) diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol index 215a661e2..f7ff4ca59 100644 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -19,7 +19,7 @@ pragma solidity ^0.4.24; contract LibMem { - + function getMemAddress(bytes memory input) internal pure @@ -30,9 +30,11 @@ contract LibMem { } return address_; } - - /// @dev Writes a uint256 into a specific position in a byte array. - /// @param dest memory adress to copy bytes to + + /// @dev Copies `length` bytes from memory location `source` to `dest`. + /// @param dest memory address to copy bytes to + /// @param source memory address to copy bytes from + /// @param length number of bytes to copy function memcpy( uint256 dest, uint256 source, @@ -41,63 +43,87 @@ contract LibMem { internal pure { - // Base cases - if(length == 0) return; - if(source == dest) return; - - // Copy bytes from source to dest - assembly { - // Compute number of complete words to copy + remaining bytes - let lenFullWords := div(add(length, 0x1F), 0x20) - let remainder := mod(length, 0x20) - if gt(remainder, 0) { - lenFullWords := sub(lenFullWords, 1) + if (length < 32) { + // Handle a partial word by reading destination and masking + // off the bits we are interested in. + // This correctly handles overlap, zero lengths and source == dest + assembly { + let mask := sub(exp(256, sub(32, length)), 1) + let s := and(mload(source), not(mask)) + let d := and(mload(dest), mask) + mstore(dest, or(s, d)) } - - // Copy full words from source to dest - let offset := 0 - let maxOffset := mul(0x20, lenFullWords) - for {offset := 0} lt(offset, maxOffset) {offset := add(offset, 0x20)} { - mstore(add(dest, offset), mload(add(source, offset))) + } else { + // Skip the O(length) loop when source == dest. + if (source == dest) { + return; } - - // Copy remaining bytes - if gt(remainder, 0) { - // Read a full word from source, containing X bytes to copy to dest. - // We only want to keep the X bytes, zeroing out the remaining bytes. - // We accomplish this by a right shift followed by a left shift. - // Example: - // Suppose a word of 8 bits has all 1's: [11111111] - // Let X = 7 (we want to copy the first 7 bits) - // Apply a right shift of 1: [01111111] - // Apply a left shift of 1: [11111110] - let sourceShiftFactor := exp(2, mul(8, sub(0x20, remainder))) - let sourceWord := mload(add(source, offset)) - let sourceBytes := mul(div(sourceWord, sourceShiftFactor), sourceShiftFactor) - - // Read a full word from dest, containing (32-X) bytes to retain. - // We need to zero out the remaining bytes to be overwritten by source, - // while retaining the (32-X) bytes we don't want to overwrite. - // We accomplish this by a left shift followed by a right shift. - // Example: - // Suppose a word of 8 bits has all 1's: [11111111] - // Let X = 7 (we want to free the first 7 bits, and retain the last bit) - // Apply a left shift of 7: [10000000] - // Apply a right shift of 7: [00000001] - let destShiftFactor := exp(2, mul(8, remainder)) - let destWord := mload(add(dest, offset)) - let destBytes := div(mul(destWord, destShiftFactor), destShiftFactor) - - // Combine the source and dest bytes. There should be no overlap: - // The source bytes run from [0..X-1] and the dest bytes from [X..31]. - // Example: - // Following the example from above, we have [11111110] - // from the source word and [00000001] from the dest word. - // Combine these words using to get [11111111]. - let combinedDestWord := or(sourceBytes, destBytes) - - // Store the combined word into dest - mstore(add(dest, offset), combinedDestWord) + + // For large copies we copy whole words at a time. The final + // word is aligned to the end of the range (instead of after the + // previous) to handle partial words. So a copy will look like this: + // + // #### + // #### + // #### + // #### + // + // We handle overlap in the source and destination range by + // changing the copying direction. This prevents us from + // overwriting parts of source that we still need to copy. + // + // This correctly handles source == dest + // + if (source > dest) { + assembly { + // We subtract 32 from `send` and `dend` because it + // is easier to compare with in the loop, and these + // are also the addresses we need for copying the + // last bytes. + length := sub(length, 32) + let send := add(source, length) + let dend := add(dest, length) + + // Remember the last 32 bytes of source + // This needs to be done here and not after the loop + // because we may have overwritten the last bytes in + // source already due to overlap. + let last := mload(send) + + // Copy whole words front to back + for {} lt(source, send) {} { + mstore(dest, mload(source)) + source := add(source, 32) + dest := add(dest, 32) + } + + // Write the last 32 bytes + mstore(dend, last) + } + } else { + assembly { + // We subtract 32 from `send` and `dend` because those + // are the starting points when copying a word at the end. + length := sub(length, 32) + let send := add(source, length) + let dend := add(dest, length) + + // Remember the first 32 bytes of source + // This needs to be done here and not after the loop + // because we may have overwritten the first bytes in + // source already due to overlap. + let first := mload(source) + + // Copy whole words back to front + for {} lt(source, send) {} { + mstore(dend, mload(send)) + send := sub(send, 32) + dend := sub(dend, 32) + } + + // Write the first 32 bytes + mstore(dest, first) + } } } } -- cgit v1.2.3 From 5db15ca54cd7e1fd90bf318d2975750dcd31cddc Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 31 May 2018 13:44:14 -0700 Subject: proxyData -> assetData --- .../LibAssetProxyDecoder/LibAssetProxyDecoder.sol | 22 +++++++++++----------- packages/contracts/test/libraries/lib_bytes.ts | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol b/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol index ba53f2769..ec27502a8 100644 --- a/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol +++ b/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol @@ -29,7 +29,7 @@ contract LibAssetProxyDecoder is string constant INVALID_ERC721_METADATA_LENGTH = "Metadata must have a length of at least 53."; /// @dev Decodes ERC721 Asset Proxy data - function decodeERC20Data(bytes memory proxyData) + function decodeERC20Data(bytes memory assetData) internal pure returns ( @@ -38,17 +38,17 @@ contract LibAssetProxyDecoder is ) { require( - proxyData.length == 21, + assetData.length == 21, INVALID_ERC20_METADATA_LENGTH ); - proxyId = uint8(proxyData[0]); - token = readAddress(proxyData, 1); + proxyId = uint8(assetData[0]); + token = readAddress(assetData, 1); return (proxyId, token); } /// @dev Decodes ERC721 Asset Proxy data - function decodeERC721Data(bytes memory proxyData) + function decodeERC721Data(bytes memory assetData) internal pure returns ( @@ -59,14 +59,14 @@ contract LibAssetProxyDecoder is ) { require( - proxyData.length >= 53, + assetData.length >= 53, INVALID_ERC721_METADATA_LENGTH ); - proxyId = uint8(proxyData[0]); - token = readAddress(proxyData, 1); - tokenId = readUint256(proxyData, 21); - if (proxyData.length > 53) { - data = readBytes(proxyData, 53); + proxyId = uint8(assetData[0]); + token = readAddress(assetData, 1); + tokenId = readUint256(assetData, 21); + if (assetData.length > 53) { + data = readBytes(assetData, 53); } return (proxyId, token, tokenId, data); diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index cd5fdcf17..9fe3a1a57 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -409,7 +409,7 @@ describe('LibBytes', () => { }); }); - describe.only('writeBytes', () => { + describe('writeBytes', () => { it('should successfully write short, nested array of bytes when it takes up the whole array)', async () => { const testBytesOffset = new BigNumber(0); const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength)); -- cgit v1.2.3 From e042e0ad32cd2ac9e707cb8e52961957f58314ce Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 31 May 2018 14:06:47 -0700 Subject: Converged on naming scheme for asset data: renamed all instances of assetMetadata, proxyData, proxyMetadata to assetData --- .../current/protocol/AssetProxy/ERC20Proxy.sol | 6 +- .../current/protocol/AssetProxy/ERC721Proxy.sol | 6 +- .../protocol/AssetProxy/MixinAssetProxy.sol | 14 +- .../protocol/AssetProxy/interfaces/IAssetProxy.sol | 8 +- .../protocol/AssetProxy/mixins/MAssetProxy.sol | 4 +- .../current/protocol/Exchange/Exchange.sol | 4 +- .../Exchange/MixinAssetProxyDispatcher.sol | 10 +- .../current/protocol/Exchange/MixinSettlement.sol | 10 +- .../protocol/Exchange/MixinWrapperFunctions.sol | 32 ++-- .../Exchange/mixins/MAssetProxyDispatcher.sol | 4 +- .../TestAssetProxyDispatcher.sol | 4 +- .../TestLibAssetProxyDecoder.sol | 8 +- packages/contracts/src/utils/match_order_tester.ts | 24 +-- packages/contracts/test/asset_proxy/decoder.ts | 40 ++--- packages/contracts/test/asset_proxy/proxies.ts | 117 ++++++--------- packages/contracts/test/exchange/core.ts | 42 +++--- packages/contracts/test/exchange/dispatcher.ts | 8 +- packages/contracts/test/exchange/libs.ts | 4 +- packages/contracts/test/exchange/match_orders.ts | 166 ++++++++++----------- .../contracts/test/exchange/signature_validator.ts | 4 +- packages/contracts/test/exchange/transactions.ts | 6 +- packages/contracts/test/exchange/wrapper.ts | 26 ++-- packages/order-utils/src/asset_proxy_utils.ts | 66 ++++---- 23 files changed, 290 insertions(+), 323 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 017f94b1a..5b4367fd9 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -36,12 +36,12 @@ contract ERC20Proxy is uint8 constant PROXY_ID = 1; /// @dev Internal version of `transferFrom`. - /// @param proxyData Encoded byte array. + /// @param assetData Encoded byte array. /// @param from Address to transfer asset from. /// @param to Address to transfer asset to. /// @param amount Amount of asset to transfer. function transferFromInternal( - bytes memory proxyData, + bytes memory assetData, address from, address to, uint256 amount @@ -52,7 +52,7 @@ contract ERC20Proxy is ( uint8 proxyId, address token - ) = decodeERC20Data(proxyData); + ) = decodeERC20Data(assetData); // Data must be intended for this proxy. uint256 length = assetMetadata.length; diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index f35e48eee..e2c445463 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -38,12 +38,12 @@ contract ERC721Proxy is string constant PROXY_ID_MISMATCH = "Proxy id in metadata does not match this proxy id."; /// @dev Internal version of `transferFrom`. - /// @param proxyData Encoded byte array. + /// @param assetData Encoded byte array. /// @param from Address to transfer asset from. /// @param to Address to transfer asset to. /// @param amount Amount of asset to transfer. function transferFromInternal( - bytes memory proxyData, + bytes memory assetData, address from, address to, uint256 amount @@ -56,7 +56,7 @@ contract ERC721Proxy is address token, uint256 tokenId, bytes memory data - ) = decodeERC721Data(proxyData); + ) = decodeERC721Data(assetData); // Data must be intended for this proxy. uint256 length = assetMetadata.length; diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol index 5fa33cbef..9032658e7 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol @@ -28,12 +28,12 @@ contract MixinAssetProxy is { /// @dev Transfers assets. Either succeeds or throws. - /// @param assetMetadata Encoded byte array. + /// @param assetData Encoded byte array. /// @param from Address to transfer asset from. /// @param to Address to transfer asset to. /// @param amount Amount of asset to transfer. function transferFrom( - bytes assetMetadata, + bytes assetData, address from, address to, uint256 amount @@ -42,7 +42,7 @@ contract MixinAssetProxy is onlyAuthorized { transferFromInternal( - assetMetadata, + assetData, from, to, amount @@ -50,12 +50,12 @@ contract MixinAssetProxy is } /// @dev Makes multiple transfers of assets. Either succeeds or throws. - /// @param assetMetadata Array of byte arrays encoded for the respective asset proxy. + /// @param assetData Array of byte arrays encoded for the respective asset proxy. /// @param from Array of addresses to transfer assets from. /// @param to Array of addresses to transfer assets to. /// @param amounts Array of amounts of assets to transfer. function batchTransferFrom( - bytes[] memory assetMetadata, + bytes[] memory assetData, address[] memory from, address[] memory to, uint256[] memory amounts @@ -63,9 +63,9 @@ contract MixinAssetProxy is public onlyAuthorized { - for (uint256 i = 0; i < assetMetadata.length; i++) { + for (uint256 i = 0; i < assetData.length; i++) { transferFromInternal( - assetMetadata[i], + assetData[i], from[i], to[i], amounts[i] diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol index 7e1848889..22f43b12f 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol @@ -26,12 +26,12 @@ contract IAssetProxy is { /// @dev Transfers assets. Either succeeds or throws. - /// @param assetMetadata Byte array encoded for the respective asset proxy. + /// @param assetData Byte array encoded for the respective asset proxy. /// @param from Address to transfer asset from. /// @param to Address to transfer asset to. /// @param amount Amount of asset to transfer. function transferFrom( - bytes assetMetadata, + bytes assetData, address from, address to, uint256 amount @@ -39,12 +39,12 @@ contract IAssetProxy is external; /// @dev Makes multiple transfers of assets. Either succeeds or throws. - /// @param assetMetadata Array of byte arrays encoded for the respective asset proxy. + /// @param assetData Array of byte arrays encoded for the respective asset proxy. /// @param from Array of addresses to transfer assets from. /// @param to Array of addresses to transfer assets to. /// @param amounts Array of amounts of assets to transfer. function batchTransferFrom( - bytes[] memory assetMetadata, + bytes[] memory assetData, address[] memory from, address[] memory to, uint256[] memory amounts diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol index de9d65a53..a52cb56f9 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol @@ -26,12 +26,12 @@ contract MAssetProxy is { /// @dev Internal version of `transferFrom`. - /// @param assetMetadata Encoded byte array. + /// @param assetData Encoded byte array. /// @param from Address to transfer asset from. /// @param to Address to transfer asset to. /// @param amount Amount of asset to transfer. function transferFromInternal( - bytes memory assetMetadata, + bytes memory assetData, address from, address to, uint256 amount diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol index b7b308069..51f99bafa 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol @@ -40,11 +40,11 @@ contract Exchange is string constant public VERSION = "2.0.1-alpha"; // Mixins are instantiated in the order they are inherited - constructor (bytes memory _zrxProxyData) + constructor (bytes memory _zrxAssetData) public MixinExchangeCore() MixinMatchOrders() - MixinSettlement(_zrxProxyData) + MixinSettlement(_zrxAssetData) MixinSignatureValidator() MixinTransactions() MixinAssetProxyDispatcher() diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol index 8f9342739..e77d81c06 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol @@ -80,12 +80,12 @@ contract MixinAssetProxyDispatcher is } /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws. - /// @param assetMetadata Byte array encoded for the respective asset proxy. + /// @param assetData Byte array encoded for the respective asset proxy. /// @param from Address to transfer token from. /// @param to Address to transfer token to. /// @param amount Amount of token to transfer. function dispatchTransferFrom( - bytes memory assetMetadata, + bytes memory assetData, address from, address to, uint256 amount @@ -96,16 +96,16 @@ contract MixinAssetProxyDispatcher is if (amount > 0) { // Lookup asset proxy - uint256 length = assetMetadata.length; + uint256 length = assetData.length; require( length > 0, LENGTH_GREATER_THAN_0_REQUIRED ); - uint8 assetProxyId = uint8(assetMetadata[length - 1]); + uint8 assetProxyId = uint8(assetData[length - 1]); IAssetProxy assetProxy = assetProxies[assetProxyId]; // transferFrom will either succeed or throw. - assetProxy.transferFrom(assetMetadata, from, to, amount); + assetProxy.transferFrom(assetData, from, to, amount); } } } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol index 646d3ed58..83e9dfdf4 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol @@ -40,7 +40,7 @@ contract MixinSettlement is bytes internal ZRX_PROXY_DATA; /// @dev Gets the ZRX metadata used for fee transfers. - function zrxProxyData() + function zrxAssetData() external view returns (bytes memory) @@ -48,13 +48,13 @@ contract MixinSettlement is return ZRX_PROXY_DATA; } - /// TODO: _zrxProxyData should be a constant in production. + /// TODO: _zrxAssetData should be a constant in production. /// @dev Constructor sets the metadata that will be used for paying ZRX fees. - /// @param _zrxProxyData Byte array containing ERC20 proxy id concatenated with address of ZRX. - constructor (bytes memory _zrxProxyData) + /// @param _zrxAssetData Byte array containing ERC20 proxy id concatenated with address of ZRX. + constructor (bytes memory _zrxAssetData) public { - ZRX_PROXY_DATA = _zrxProxyData; + ZRX_PROXY_DATA = _zrxAssetData; } /// @dev Settles an order by transferring assets between counterparties. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index 0ad0710ce..0d9888703 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -91,12 +91,12 @@ contract MixinWrapperFunctions is // | | 0x0E0 | | 8. takerFeeAmount | // | | 0x100 | | 9. expirationTimeSeconds | // | | 0x120 | | 10. salt | - // | | 0x140 | | 11. Offset to makerAssetProxyMetadata (*) | - // | | 0x160 | | 12. Offset to takerAssetProxyMetadata (*) | - // | | 0x180 | 32 | makerAssetProxyMetadata Length | - // | | 0x1A0 | ** | makerAssetProxyMetadata Contents | - // | | 0x1C0 | 32 | takerAssetProxyMetadata Length | - // | | 0x1E0 | ** | takerAssetProxyMetadata Contents | + // | | 0x140 | | 11. Offset to makerAssetData (*) | + // | | 0x160 | | 12. Offset to takerAssetData (*) | + // | | 0x180 | 32 | makerAssetData Length | + // | | 0x1A0 | ** | makerAssetData Contents | + // | | 0x1C0 | 32 | takerAssetData Length | + // | | 0x1E0 | ** | takerAssetData Contents | // | | 0x200 | 32 | signature Length | // | | 0x220 | ** | signature Contents | @@ -163,43 +163,43 @@ contract MixinWrapperFunctions is mstore(add(dataAreaEnd, 0xE0), mload(add(sourceOffset, 0xE0))) // takerFeeAmount mstore(add(dataAreaEnd, 0x100), mload(add(sourceOffset, 0x100))) // expirationTimeSeconds mstore(add(dataAreaEnd, 0x120), mload(add(sourceOffset, 0x120))) // salt - mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to makerAssetProxyMetadata - mstore(add(dataAreaEnd, 0x160), mload(add(sourceOffset, 0x160))) // Offset to takerAssetProxyMetadata + mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to makerAssetData + mstore(add(dataAreaEnd, 0x160), mload(add(sourceOffset, 0x160))) // Offset to takerAssetData dataAreaEnd := add(dataAreaEnd, 0x180) sourceOffset := add(sourceOffset, 0x180) - // Write offset to + // Write offset to mstore(add(dataAreaStart, mul(10, 0x20)), sub(dataAreaEnd, dataAreaStart)) - // Calculate length of + // Calculate length of arrayLenBytes := mload(sourceOffset) sourceOffset := add(sourceOffset, 0x20) arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20) - // Write length of + // Write length of mstore(dataAreaEnd, arrayLenBytes) dataAreaEnd := add(dataAreaEnd, 0x20) - // Write contents of + // Write contents of for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} { mstore(dataAreaEnd, mload(sourceOffset)) dataAreaEnd := add(dataAreaEnd, 0x20) sourceOffset := add(sourceOffset, 0x20) } - // Write offset to + // Write offset to mstore(add(dataAreaStart, mul(11, 0x20)), sub(dataAreaEnd, dataAreaStart)) - // Calculate length of + // Calculate length of arrayLenBytes := mload(sourceOffset) sourceOffset := add(sourceOffset, 0x20) arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20) - // Write length of + // Write length of mstore(dataAreaEnd, arrayLenBytes) dataAreaEnd := add(dataAreaEnd, 0x20) - // Write contents of + // Write contents of for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} { mstore(dataAreaEnd, mload(sourceOffset)) dataAreaEnd := add(dataAreaEnd, 0x20) diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol index 87c5f6361..82eafb529 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol @@ -33,12 +33,12 @@ contract MAssetProxyDispatcher is ); /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws. - /// @param assetMetadata Byte array encoded for the respective asset proxy. + /// @param assetData Byte array encoded for the respective asset proxy. /// @param from Address to transfer token from. /// @param to Address to transfer token to. /// @param amount Amount of token to transfer. function dispatchTransferFrom( - bytes memory assetMetadata, + bytes memory assetData, address from, address to, uint256 amount diff --git a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol index 11ca0617d..2ae69e0ef 100644 --- a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol @@ -23,12 +23,12 @@ import "../../protocol/Exchange/MixinAssetProxyDispatcher.sol"; contract TestAssetProxyDispatcher is MixinAssetProxyDispatcher { function publicDispatchTransferFrom( - bytes memory assetMetadata, + bytes memory assetData, address from, address to, uint256 amount) public { - dispatchTransferFrom(assetMetadata, from, to, amount); + dispatchTransferFrom(assetData, from, to, amount); } } diff --git a/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol b/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol index e4a7de71d..6d2866656 100644 --- a/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol +++ b/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol @@ -26,16 +26,16 @@ contract TestLibAssetProxyDecoder is { /// @dev Decodes ERC721 Asset Proxy data - function publicDecodeERC20Data(bytes memory proxyData) + function publicDecodeERC20Data(bytes memory assetData) public pure returns (uint8, address) { - return decodeERC20Data(proxyData); + return decodeERC20Data(assetData); } /// @dev Decodes ERC721 Asset Proxy data - function publicDecodeERC721Data(bytes memory proxyData) + function publicDecodeERC721Data(bytes memory assetData) public pure returns ( @@ -45,6 +45,6 @@ contract TestLibAssetProxyDecoder is bytes memory ) { - return decodeERC721Data(proxyData); + return decodeERC721Data(assetData); } } diff --git a/packages/contracts/src/utils/match_order_tester.ts b/packages/contracts/src/utils/match_order_tester.ts index f4f7f965b..fbb1b99db 100644 --- a/packages/contracts/src/utils/match_order_tester.ts +++ b/packages/contracts/src/utils/match_order_tester.ts @@ -237,11 +237,11 @@ export class MatchOrderTester { const expectedNewERC20BalancesByOwner = _.cloneDeep(erc20BalancesByOwner); const expectedNewERC721TokenIdsByOwner = _.cloneDeep(erc721TokenIdsByOwner); // Left Maker Asset (Right Taker Asset) - const makerAssetProxyIdLeft = assetProxyUtils.decodeProxyDataId(signedOrderLeft.makerAssetData); + const makerAssetProxyIdLeft = assetProxyUtils.decodeAssetDataId(signedOrderLeft.makerAssetData); if (makerAssetProxyIdLeft === AssetProxyId.ERC20) { // Decode asset data - const erc20ProxyData = assetProxyUtils.decodeERC20ProxyData(signedOrderLeft.makerAssetData); - const makerAssetAddressLeft = erc20ProxyData.tokenAddress; + const erc20AssetData = assetProxyUtils.decodeERC20AssetData(signedOrderLeft.makerAssetData); + const makerAssetAddressLeft = erc20AssetData.tokenAddress; const takerAssetAddressRight = makerAssetAddressLeft; // Left Maker expectedNewERC20BalancesByOwner[makerAddressLeft][makerAssetAddressLeft] = expectedNewERC20BalancesByOwner[ @@ -259,9 +259,9 @@ export class MatchOrderTester { ][makerAssetAddressLeft].add(expectedTransferAmounts.amountReceivedByTaker); } else if (makerAssetProxyIdLeft === AssetProxyId.ERC721) { // Decode asset data - const erc721ProxyData = assetProxyUtils.decodeERC721ProxyData(signedOrderLeft.makerAssetData); - const makerAssetAddressLeft = erc721ProxyData.tokenAddress; - const makerAssetIdLeft = erc721ProxyData.tokenId; + const erc721AssetData = assetProxyUtils.decodeERC721AssetData(signedOrderLeft.makerAssetData); + const makerAssetAddressLeft = erc721AssetData.tokenAddress; + const makerAssetIdLeft = erc721AssetData.tokenId; const takerAssetAddressRight = makerAssetAddressLeft; const takerAssetIdRight = makerAssetIdLeft; // Left Maker @@ -272,11 +272,11 @@ export class MatchOrderTester { } // Left Taker Asset (Right Maker Asset) // Note: This exchange is only between the order makers: the Taker does not receive any of the left taker asset. - const takerAssetProxyIdLeft = assetProxyUtils.decodeProxyDataId(signedOrderLeft.takerAssetData); + const takerAssetProxyIdLeft = assetProxyUtils.decodeAssetDataId(signedOrderLeft.takerAssetData); if (takerAssetProxyIdLeft === AssetProxyId.ERC20) { // Decode asset data - const erc20ProxyData = assetProxyUtils.decodeERC20ProxyData(signedOrderLeft.takerAssetData); - const takerAssetAddressLeft = erc20ProxyData.tokenAddress; + const erc20AssetData = assetProxyUtils.decodeERC20AssetData(signedOrderLeft.takerAssetData); + const takerAssetAddressLeft = erc20AssetData.tokenAddress; const makerAssetAddressRight = takerAssetAddressLeft; // Left Maker expectedNewERC20BalancesByOwner[makerAddressLeft][takerAssetAddressLeft] = expectedNewERC20BalancesByOwner[ @@ -290,9 +290,9 @@ export class MatchOrderTester { ); } else if (takerAssetProxyIdLeft === AssetProxyId.ERC721) { // Decode asset data - const erc721ProxyData = assetProxyUtils.decodeERC721ProxyData(signedOrderRight.makerAssetData); - const makerAssetAddressRight = erc721ProxyData.tokenAddress; - const makerAssetIdRight = erc721ProxyData.tokenId; + const erc721AssetData = assetProxyUtils.decodeERC721AssetData(signedOrderRight.makerAssetData); + const makerAssetAddressRight = erc721AssetData.tokenAddress; + const makerAssetIdRight = erc721AssetData.tokenId; const takerAssetAddressLeft = makerAssetAddressRight; const takerAssetIdLeft = makerAssetIdRight; // Right Maker diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 0f1413ff1..712ef8656 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -12,7 +12,7 @@ import { artifacts } from '../../src/utils/artifacts'; import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; -import { AssetProxyId, ERC20ProxyData, ERC721ProxyData, ProxyData } from '../../src/utils/types'; +import { AssetProxyId, ERC20AssetData, ERC721AssetData, AssetData } from '../../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); @@ -45,21 +45,21 @@ describe('LibAssetProxyDecoder', () => { describe('LibAssetProxyDecoder', () => { it('should correctly decode ERC20 proxy data)', async () => { - const encodedProxyData = assetProxyUtils.encodeERC20ProxyData(testAddress); - const expectedDecodedProxyData = assetProxyUtils.decodeERC20ProxyData(encodedProxyData); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(testAddress); + const expectedDecodedAssetData = assetProxyUtils.decodeERC20AssetData(encodedAssetData); let decodedAssetProxyId: number; let decodedTokenAddress: string; [decodedAssetProxyId, decodedTokenAddress] = await testAssetProxyDecoder.publicDecodeERC20Data.callAsync( - encodedProxyData, + encodedAssetData, ); - expect(decodedAssetProxyId).to.be.equal(expectedDecodedProxyData.assetProxyId); - expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); + expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId); + expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress); }); it('should correctly decode ERC721 proxy data', async () => { const tokenId = ZeroEx.generatePseudoRandomSalt(); - const encodedProxyData = assetProxyUtils.encodeERC721ProxyData(testAddress, tokenId); - const expectedDecodedProxyData = assetProxyUtils.decodeERC721ProxyData(encodedProxyData); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId); + const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData); let decodedAssetProxyId: number; let decodedTokenAddress: string; let decodedTokenId: BigNumber; @@ -69,18 +69,18 @@ describe('LibAssetProxyDecoder', () => { decodedTokenAddress, decodedTokenId, decodedData, - ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedProxyData); - expect(decodedAssetProxyId).to.be.equal(expectedDecodedProxyData.assetProxyId); - expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); - expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedProxyData.tokenId); - expect(decodedData).to.be.equal(expectedDecodedProxyData.data); + ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedAssetData); + expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId); + expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress); + expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedAssetData.tokenId); + expect(decodedData).to.be.equal(expectedDecodedAssetData.data); }); it('should correctly decode ERC721 proxy data with receiver data', async () => { const tokenId = ZeroEx.generatePseudoRandomSalt(); const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())) + 'FFFF'; - const encodedProxyData = assetProxyUtils.encodeERC721ProxyData(testAddress, tokenId, data); - const expectedDecodedProxyData = assetProxyUtils.decodeERC721ProxyData(encodedProxyData); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId, data); + const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData); let decodedAssetProxyId: number; let decodedTokenAddress: string; let decodedTokenId: BigNumber; @@ -90,11 +90,11 @@ describe('LibAssetProxyDecoder', () => { decodedTokenAddress, decodedTokenId, decodedData, - ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedProxyData); - expect(decodedAssetProxyId).to.be.equal(expectedDecodedProxyData.assetProxyId); - expect(decodedTokenAddress).to.be.equal(expectedDecodedProxyData.tokenAddress); - expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedProxyData.tokenId); - expect(decodedData).to.be.equal(expectedDecodedProxyData.data); + ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedAssetData); + expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId); + expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress); + expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedAssetData.tokenId); + expect(decodedData).to.be.equal(expectedDecodedAssetData.data); }); }); }); diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index 4995e95a0..d6bc8163b 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -107,13 +107,13 @@ describe('Asset Transfer Proxies', () => { describe('transferFrom', () => { it('should successfully transfer tokens', async () => { // Construct metadata for ERC20 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(10); await web3Wrapper.awaitTransactionSuccessAsync( await erc20Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, @@ -133,13 +133,13 @@ describe('Asset Transfer Proxies', () => { it('should do nothing if transferring 0 amount of a token', async () => { // Construct metadata for ERC20 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(0); await web3Wrapper.awaitTransactionSuccessAsync( await erc20Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, @@ -159,7 +159,7 @@ describe('Asset Transfer Proxies', () => { it('should throw if allowances are too low', async () => { // Construct metadata for ERC20 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Create allowance less than transfer amount. Set allowance on proxy. const allowance = new BigNumber(0); const transferAmount = new BigNumber(10); @@ -172,7 +172,7 @@ describe('Asset Transfer Proxies', () => { // Perform a transfer; expect this to fail. return expectRevertOrAlwaysFailingTransactionAsync( erc20Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, transferAmount, @@ -183,19 +183,13 @@ describe('Asset Transfer Proxies', () => { it('should throw if requesting address is not authorized', async () => { // Construct metadata for ERC20 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(10); return expectRevertOrAlwaysFailingTransactionAsync( - erc20Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, - makerAddress, - takerAddress, - amount, - { - from: notAuthorized, - }, - ), + erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, { + from: notAuthorized, + }), ); }); }); @@ -204,16 +198,16 @@ describe('Asset Transfer Proxies', () => { it('should succesfully make multiple token transfers', async () => { const erc20Balances = await erc20Wrapper.getBalancesAsync(); - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); const amount = new BigNumber(10); const numTransfers = 2; - const assetMetadata = _.times(numTransfers, () => encodedProxyMetadata); + const assetData = _.times(numTransfers, () => encodedAssetData); const fromAddresses = _.times(numTransfers, () => makerAddress); const toAddresses = _.times(numTransfers, () => takerAddress); const amounts = _.times(numTransfers, () => amount); const txHash = await erc20Proxy.batchTransferFrom.sendTransactionAsync( - assetMetadata, + assetData, fromAddresses, toAddresses, amounts, @@ -235,17 +229,17 @@ describe('Asset Transfer Proxies', () => { }); it('should throw if not called by an authorized address', async () => { - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); const amount = new BigNumber(10); const numTransfers = 2; - const assetMetadata = _.times(numTransfers, () => encodedProxyMetadata); + const assetData = _.times(numTransfers, () => encodedAssetData); const fromAddresses = _.times(numTransfers, () => makerAddress); const toAddresses = _.times(numTransfers, () => takerAddress); const amounts = _.times(numTransfers, () => amount); return expectRevertOrAlwaysFailingTransactionAsync( erc20Proxy.batchTransferFrom.sendTransactionAsync( - assetMetadata, + encodedAssetData, fromAddresses, toAddresses, amounts, @@ -265,10 +259,7 @@ describe('Asset Transfer Proxies', () => { describe('transferFrom', () => { it('should successfully transfer tokens', async () => { // Construct metadata for ERC721 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( - erc721Token.address, - erc721MakerTokenId, - ); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); @@ -276,7 +267,7 @@ describe('Asset Transfer Proxies', () => { const amount = new BigNumber(1); await web3Wrapper.awaitTransactionSuccessAsync( await erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, @@ -291,10 +282,7 @@ describe('Asset Transfer Proxies', () => { it('should call onERC721Received when transferring to a smart contract', async () => { // Construct metadata for ERC721 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( - erc721Token.address, - erc721MakerTokenId, - ); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); @@ -302,7 +290,7 @@ describe('Asset Transfer Proxies', () => { const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); const txHash = await erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, erc721Receiver.address, amount, @@ -327,7 +315,7 @@ describe('Asset Transfer Proxies', () => { it('should call onERC721Received when transferring to a smart contract and receive extra data', async () => { // Construct metadata for ERC721 proxy const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( + const encodedAssetData = assetProxyUtils.encodeERC721AssetData( erc721Token.address, erc721MakerTokenId, data, @@ -339,7 +327,7 @@ describe('Asset Transfer Proxies', () => { const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); const txHash = await erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, erc721Receiver.address, amount, @@ -363,10 +351,7 @@ describe('Asset Transfer Proxies', () => { it('should throw if receiving contract does not have onERC721Received', async () => { // Construct metadata for ERC721 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( - erc721Token.address, - erc721MakerTokenId, - ); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); @@ -375,7 +360,7 @@ describe('Asset Transfer Proxies', () => { const amount = new BigNumber(1); return expect( erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, erc20Proxy.address, // the ERC20 proxy does not have an ERC721 receiver amount, @@ -386,10 +371,7 @@ describe('Asset Transfer Proxies', () => { it('should throw if transferring 0 amount of a token', async () => { // Construct metadata for ERC721 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( - erc721Token.address, - erc721MakerTokenId, - ); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); @@ -397,7 +379,7 @@ describe('Asset Transfer Proxies', () => { const amount = new BigNumber(0); return expectRevertOrAlwaysFailingTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, @@ -408,10 +390,7 @@ describe('Asset Transfer Proxies', () => { it('should throw if transferring > 1 amount of a token', async () => { // Construct metadata for ERC721 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( - erc721Token.address, - erc721MakerTokenId, - ); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); @@ -419,7 +398,7 @@ describe('Asset Transfer Proxies', () => { const amount = new BigNumber(500); return expectRevertOrAlwaysFailingTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, @@ -430,10 +409,7 @@ describe('Asset Transfer Proxies', () => { it('should throw if allowances are too low', async () => { // Construct metadata for ERC721 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( - erc721Token.address, - erc721MakerTokenId, - ); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Remove transfer approval for makerAddress. await web3Wrapper.awaitTransactionSuccessAsync( await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, false, { @@ -444,29 +420,20 @@ describe('Asset Transfer Proxies', () => { // Perform a transfer; expect this to fail. const amount = new BigNumber(1); return expectRevertOrAlwaysFailingTransactionAsync( - erc20Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, - makerAddress, - takerAddress, - amount, - { - from: notAuthorized, - }, - ), + erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, { + from: notAuthorized, + }), ); }); it('should throw if requesting address is not authorized', async () => { // Construct metadata for ERC721 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData( - erc721Token.address, - erc721MakerTokenId, - ); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(1); return expectRevertOrAlwaysFailingTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, @@ -482,16 +449,16 @@ describe('Asset Transfer Proxies', () => { const [makerTokenIdA, makerTokenIdB] = erc721TokensById[makerAddress][erc721Token.address]; const numTransfers = 2; - const assetMetadata = [ - assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdA), - assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdB), + const assetData = [ + assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdA), + assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdB), ]; const fromAddresses = _.times(numTransfers, () => makerAddress); const toAddresses = _.times(numTransfers, () => takerAddress); const amounts = _.times(numTransfers, () => new BigNumber(1)); const txHash = await erc721Proxy.batchTransferFrom.sendTransactionAsync( - assetMetadata, + assetData, fromAddresses, toAddresses, amounts, @@ -514,9 +481,9 @@ describe('Asset Transfer Proxies', () => { const [makerTokenIdA, makerTokenIdB] = erc721TokensById[makerAddress][erc721Token.address]; const numTransfers = 2; - const assetMetadata = [ - assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdA), - assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdB), + const assetData = [ + assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdA), + assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdB), ]; const fromAddresses = _.times(numTransfers, () => makerAddress); const toAddresses = _.times(numTransfers, () => takerAddress); @@ -524,7 +491,7 @@ describe('Asset Transfer Proxies', () => { return expectRevertOrAlwaysFailingTransactionAsync( erc721Proxy.batchTransferFrom.sendTransactionAsync( - assetMetadata, + encodedAssetData, fromAddresses, toAddresses, amounts, diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index bee74cca8..8d3c3a940 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -87,7 +87,7 @@ describe('Exchange core', () => { artifacts.Exchange, provider, txDefaults, - assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + assetProxyUtils.encodeERC20AssetData(zrxToken.address), ); exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); @@ -114,8 +114,8 @@ describe('Exchange core', () => { exchangeAddress: exchange.address, makerAddress, feeRecipientAddress, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress), }; const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); @@ -711,8 +711,8 @@ describe('Exchange core', () => { signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -737,8 +737,8 @@ describe('Exchange core', () => { signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -759,8 +759,8 @@ describe('Exchange core', () => { signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -781,8 +781,8 @@ describe('Exchange core', () => { signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(2), takerAssetAmount: new BigNumber(1), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -803,8 +803,8 @@ describe('Exchange core', () => { signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(500), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -825,8 +825,8 @@ describe('Exchange core', () => { signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(0), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -845,9 +845,9 @@ describe('Exchange core', () => { const makerAssetId = erc721MakerAssetIds[0]; signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerAssetAddress), + takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -885,9 +885,9 @@ describe('Exchange core', () => { const takerAssetId = erc721TakerAssetIds[0]; signedOrder = orderFactory.newSignedOrder({ takerAssetAmount: new BigNumber(1), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerAssetAddress), + makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress), }); // Verify pre-conditions const initialOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId); diff --git a/packages/contracts/test/exchange/dispatcher.ts b/packages/contracts/test/exchange/dispatcher.ts index 02d43a132..9e113e47d 100644 --- a/packages/contracts/test/exchange/dispatcher.ts +++ b/packages/contracts/test/exchange/dispatcher.ts @@ -275,13 +275,13 @@ describe('AssetProxyDispatcher', () => { constants.AWAIT_TRANSACTION_MINED_MS, ); // Construct metadata for ERC20 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(10); await web3Wrapper.awaitTransactionSuccessAsync( await assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, @@ -301,12 +301,12 @@ describe('AssetProxyDispatcher', () => { it('should throw if dispatching to unregistered proxy', async () => { // Construct metadata for ERC20 proxy - const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); + const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(10); return expectRevertOrAlwaysFailingTransactionAsync( assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync( - encodedProxyMetadata, + encodedAssetData, makerAddress, takerAddress, amount, diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts index b12934014..eff05981d 100644 --- a/packages/contracts/test/exchange/libs.ts +++ b/packages/contracts/test/exchange/libs.ts @@ -38,8 +38,8 @@ describe('Exchange libs', () => { exchangeAddress: libs.address, makerAddress, feeRecipientAddress: addressUtils.generatePseudoRandomAddress(), - makerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()), + makerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()), + takerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()), }; const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts index aab3308ae..f34cbee1b 100644 --- a/packages/contracts/test/exchange/match_orders.ts +++ b/packages/contracts/test/exchange/match_orders.ts @@ -96,7 +96,7 @@ describe('matchOrders', () => { artifacts.Exchange, provider, txDefaults, - assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + assetProxyUtils.encodeERC20AssetData(zrxToken.address), ); exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); @@ -122,8 +122,8 @@ describe('matchOrders', () => { const defaultOrderParams = { ...constants.STATIC_ORDER_PARAMS, exchangeAddress: exchange.address, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), }; const privateKeyLeft = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddressLeft)]; orderFactoryLeft = new OrderFactory(privateKeyLeft, defaultOrderParams); @@ -148,16 +148,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -182,16 +182,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -227,16 +227,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -261,16 +261,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -295,16 +295,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -334,8 +334,8 @@ describe('matchOrders', () => { // branch in the contract twice for this test. const signedOrderRight2 = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -364,8 +364,8 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -373,8 +373,8 @@ describe('matchOrders', () => { const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -404,8 +404,8 @@ describe('matchOrders', () => { // branch in the contract twice for this test. const signedOrderLeft2 = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -437,16 +437,16 @@ describe('matchOrders', () => { const feeRecipientAddress = feeRecipientAddressLeft; const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress, @@ -465,16 +465,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -494,16 +494,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -523,16 +523,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -552,16 +552,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -581,16 +581,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: makerAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: makerAddressRight, @@ -609,16 +609,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -635,16 +635,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -661,16 +661,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -691,16 +691,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -721,16 +721,16 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressRight, @@ -752,16 +752,16 @@ describe('matchOrders', () => { const erc721TokenToTransfer = erc721LeftMakerAssetIds[0]; const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: new BigNumber(1), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: new BigNumber(1), feeRecipientAddress: feeRecipientAddressRight, @@ -787,16 +787,16 @@ describe('matchOrders', () => { const erc721TokenToTransfer = erc721RightMakerAssetIds[0]; const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: new BigNumber(1), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = orderFactoryRight.newSignedOrder({ makerAddress: makerAddressRight, - makerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetAmount: new BigNumber(1), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressRight, diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts index 79db620b4..c39fd6ee4 100644 --- a/packages/contracts/test/exchange/signature_validator.ts +++ b/packages/contracts/test/exchange/signature_validator.ts @@ -42,8 +42,8 @@ describe('MixinSignatureValidator', () => { exchangeAddress: signatureValidator.address, makerAddress, feeRecipientAddress: addressUtils.generatePseudoRandomAddress(), - makerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()), + makerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()), + takerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()), }; const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts index 7897fa558..8c5bc7bec 100644 --- a/packages/contracts/test/exchange/transactions.ts +++ b/packages/contracts/test/exchange/transactions.ts @@ -72,7 +72,7 @@ describe('Exchange transactions', () => { artifacts.Exchange, provider, txDefaults, - assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + assetProxyUtils.encodeERC20AssetData(zrxToken.address), ); exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); @@ -91,8 +91,8 @@ describe('Exchange transactions', () => { exchangeAddress: exchange.address, makerAddress, feeRecipientAddress, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerTokenAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerTokenAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerTokenAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerTokenAddress), }; makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)]; takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)]; diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts index 258e1ff81..b66cff90a 100644 --- a/packages/contracts/test/exchange/wrapper.ts +++ b/packages/contracts/test/exchange/wrapper.ts @@ -81,7 +81,7 @@ describe('Exchange wrappers', () => { artifacts.Exchange, provider, txDefaults, - assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + assetProxyUtils.encodeERC20AssetData(zrxToken.address), ); exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner); @@ -108,8 +108,8 @@ describe('Exchange wrappers', () => { exchangeAddress: exchange.address, makerAddress, feeRecipientAddress, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerAssetAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress), }; const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); @@ -304,7 +304,7 @@ describe('Exchange wrappers', () => { const signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: makerZRXBalance, makerFee: new BigNumber(1), - makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -316,7 +316,7 @@ describe('Exchange wrappers', () => { const signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(makerZRXAllowance), makerFee: new BigNumber(1), - makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -328,7 +328,7 @@ describe('Exchange wrappers', () => { const signedOrder = orderFactory.newSignedOrder({ takerAssetAmount: takerZRXBalance, takerFee: new BigNumber(1), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -340,7 +340,7 @@ describe('Exchange wrappers', () => { const signedOrder = orderFactory.newSignedOrder({ takerAssetAmount: new BigNumber(takerZRXAllowance), takerFee: new BigNumber(1), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress); const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -354,8 +354,8 @@ describe('Exchange wrappers', () => { const signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), - makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId), - takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId), + makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), + takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), }); // Verify pre-conditions const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); @@ -692,7 +692,7 @@ describe('Exchange wrappers', () => { signedOrders = [ orderFactory.newSignedOrder(), orderFactory.newSignedOrder({ - takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), orderFactory.newSignedOrder(), ]; @@ -785,7 +785,7 @@ describe('Exchange wrappers', () => { signedOrders = [ orderFactory.newSignedOrder(), orderFactory.newSignedOrder({ - takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), orderFactory.newSignedOrder(), ]; @@ -874,7 +874,7 @@ describe('Exchange wrappers', () => { signedOrders = [ orderFactory.newSignedOrder(), orderFactory.newSignedOrder({ - makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), orderFactory.newSignedOrder(), ]; @@ -967,7 +967,7 @@ describe('Exchange wrappers', () => { signedOrders = [ orderFactory.newSignedOrder(), orderFactory.newSignedOrder({ - makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address), + makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), orderFactory.newSignedOrder(), ]; diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index 8255376a1..1f1e49f0f 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -41,7 +41,7 @@ export const assetProxyUtils = { const value = new BigNumber(formattedValue, 16); return value; }, - encodeERC20ProxyData(tokenAddress: string): string { + encodeERC20AssetData(tokenAddress: string): string { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC20); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); const encodedMetadata = Buffer.concat([encodedAddress, encodedAssetProxyId]); @@ -53,11 +53,11 @@ export const assetProxyUtils = { if (encodedProxyMetadata.byteLength !== ERC20_PROXY_METADATA_BYTE_LENGTH) { throw new Error( `Could not decode ERC20 Proxy Data. Expected length of encoded data to be 21. Got ${ - encodedProxyMetadata.byteLength + encodedAssetData.byteLength }`, ); } - const encodedAssetProxyId = encodedProxyMetadata.slice(-1); + const encodedAssetProxyId = encodedAssetData.slice(-1); const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); if (assetProxyId !== AssetProxyId.ERC20) { throw new Error( @@ -69,13 +69,13 @@ export const assetProxyUtils = { const addressOffset = ERC20_PROXY_METADATA_BYTE_LENGTH - 1; const encodedTokenAddress = encodedProxyMetadata.slice(0, addressOffset); const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); - const erc20ProxyData = { + const erc20AssetData = { assetProxyId, tokenAddress, }; - return erc20ProxyData; + return erc20AssetData; }, - encodeERC721ProxyData(tokenAddress: string, tokenId: BigNumber, data?: string): string { + encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber, data?: string): string { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC721); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); const encodedTokenId = assetProxyUtils.encodeUint256(tokenId); @@ -89,16 +89,16 @@ export const assetProxyUtils = { const encodedMetadataHex = ethUtil.bufferToHex(encodedMetadata); return encodedMetadataHex; }, - decodeERC721ProxyData(proxyData: string): ERC721ProxyData { - const encodedProxyMetadata = ethUtil.toBuffer(proxyData); - if (encodedProxyMetadata.byteLength < ERC721_PROXY_METADATA_BYTE_LENGTH) { + decodeERC721AssetData(assetData: string): ERC721AssetData { + const encodedAssetData = ethUtil.toBuffer(assetData); + if (encodedAssetData.byteLength < ERC721_PROXY_METADATA_BYTE_LENGTH) { throw new Error( `Could not decode ERC20 Proxy Data. Expected length of encoded data to be at least 53. Got ${ - encodedProxyMetadata.byteLength + encodedAssetData.byteLength }`, ); } - const encodedAssetProxyId = encodedProxyMetadata.slice(-1); + const encodedAssetProxyId = encodedAssetData.slice(-1); const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); if (assetProxyId !== AssetProxyId.ERC721) { throw new Error( @@ -115,57 +115,57 @@ export const assetProxyUtils = { const tokenId = assetProxyUtils.decodeUint256(encodedTokenId); const nullData = '0x'; let data = nullData; - if (encodedProxyMetadata.byteLength > 53) { - const encodedDataLength = encodedProxyMetadata.slice(53, 85); + if (encodedAssetData.byteLength > 53) { + const encodedDataLength = encodedAssetData.slice(53, 85); const dataLength = assetProxyUtils.decodeUint256(encodedDataLength); - const expectedDataLength = new BigNumber(encodedProxyMetadata.byteLength - 85); + const expectedDataLength = new BigNumber(encodedAssetData.byteLength - 85); if (!dataLength.equals(expectedDataLength)) { throw new Error( `Data length (${dataLength}) does not match actual length of data (${expectedDataLength})`, ); } - const encodedData = encodedProxyMetadata.slice(85); + const encodedData = encodedAssetData.slice(85); data = ethUtil.bufferToHex(encodedData); } - const erc721ProxyData: ERC721ProxyData = { + const erc721AssetData: ERC721AssetData = { assetProxyId, tokenAddress, tokenId, data, }; - return erc721ProxyData; + return erc721AssetData; }, - decodeProxyDataId(proxyData: string): AssetProxyId { - const encodedProxyMetadata = ethUtil.toBuffer(proxyData); - if (encodedProxyMetadata.byteLength < 1) { + decodeAssetDataId(assetData: string): AssetProxyId { + const encodedAssetData = ethUtil.toBuffer(assetData); + if (encodedAssetData.byteLength < 1) { throw new Error( `Could not decode Proxy Data. Expected length of encoded data to be at least 1. Got ${ - encodedProxyMetadata.byteLength + encodedAssetData.byteLength }`, ); } - const encodedAssetProxyId = encodedProxyMetadata.slice(-1); + const encodedAssetProxyId = encodedAssetData.slice(-1); const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); return assetProxyId; }, - decodeProxyData(proxyData: string): ProxyData { - const assetProxyId = assetProxyUtils.decodeProxyDataId(proxyData); + decodeAssetData(assetData: string): AssetData { + const assetProxyId = assetProxyUtils.decodeAssetDataId(assetData); switch (assetProxyId) { case AssetProxyId.ERC20: - const erc20ProxyData = assetProxyUtils.decodeERC20ProxyData(proxyData); - const generalizedERC20ProxyData = { + const erc20AssetData = assetProxyUtils.decodeERC20AssetData(assetData); + const generalizedERC20AssetData = { assetProxyId, - tokenAddress: erc20ProxyData.tokenAddress, + tokenAddress: erc20AssetData.tokenAddress, }; - return generalizedERC20ProxyData; + return generalizedERC20AssetData; case AssetProxyId.ERC721: - const erc721ProxyData = assetProxyUtils.decodeERC721ProxyData(proxyData); - const generaliedERC721ProxyData = { + const erc721AssetData = assetProxyUtils.decodeERC721AssetData(assetData); + const generaliedERC721AssetData = { assetProxyId, - tokenAddress: erc721ProxyData.tokenAddress, - data: erc721ProxyData.tokenId, + tokenAddress: erc721AssetData.tokenAddress, + data: erc721AssetData.tokenId, }; - return generaliedERC721ProxyData; + return generaliedERC721AssetData; default: throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); } -- cgit v1.2.3 From 249a1e6d8d129d6b067a4ddadfb4b94733ddfc07 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 31 May 2018 16:31:00 -0700 Subject: Removed the LibAssetProxyDecoder. Merged decode functions into the proxies. This way they can still be used by the forwarding contract. TestAssetDataDecoders inherits them in the same way the forwarding contract would --- packages/contracts/compiler.json | 2 +- packages/contracts/package.json | 2 +- .../current/protocol/AssetProxy/ERC20Proxy.sol | 24 ++++++- .../current/protocol/AssetProxy/ERC721Proxy.sol | 29 ++++++++- .../TestAssetDataDecoders.sol | 52 +++++++++++++++ .../TestLibAssetProxyDecoder.sol | 50 --------------- .../LibAssetProxyDecoder/LibAssetProxyDecoder.sol | 74 ---------------------- packages/contracts/src/utils/artifacts.ts | 4 +- packages/contracts/src/utils/types.ts | 2 +- packages/contracts/test/asset_proxy/decoder.ts | 10 +-- 10 files changed, 109 insertions(+), 140 deletions(-) create mode 100644 packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol delete mode 100644 packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol delete mode 100644 packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol diff --git a/packages/contracts/compiler.json b/packages/contracts/compiler.json index 464137d9b..6ef8e6a95 100644 --- a/packages/contracts/compiler.json +++ b/packages/contracts/compiler.json @@ -29,7 +29,7 @@ "MixinAuthorizable", "MultiSigWallet", "MultiSigWalletWithTimeLock", - "TestLibAssetProxyDecoder", + "TestAssetDataDecoders", "TestAssetProxyDispatcher", "TestLibBytes", "TestLibMem", diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 658f5ed60..e436ae15e 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -30,7 +30,7 @@ "test:circleci": "yarn test" }, "config": { - "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|DummyERC721Receiver|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibAssetProxyDecoder|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" + "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|DummyERC721Receiver|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetDataDecoders|TestAssetProxyDispatcher|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" }, "repository": { "type": "git", diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 5b4367fd9..11383adaf 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -20,14 +20,13 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; -import "../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol"; +import "../../tokens/ERC20Token/IERC20Token.sol"; import "./MixinAssetProxy.sol"; import "./MixinAuthorizable.sol"; import "../../tokens/ERC20Token/IERC20Token.sol"; contract ERC20Proxy is LibBytes, - LibAssetProxyDecoder, MixinAssetProxy, MixinAuthorizable { @@ -52,7 +51,7 @@ contract ERC20Proxy is ( uint8 proxyId, address token - ) = decodeERC20Data(assetData); + ) = decodeERC20AssetData(assetData); // Data must be intended for this proxy. uint256 length = assetMetadata.length; @@ -79,4 +78,23 @@ contract ERC20Proxy is { return PROXY_ID; } + + /// @dev Decodes ERC20 Asset Proxy data + function decodeERC20AssetData(bytes memory assetData) + internal + pure + returns ( + uint8 proxyId, + address token + ) + { + require( + assetData.length == 21, + INVALID_ASSET_DATA_LENGTH + ); + proxyId = uint8(assetData[0]); + token = readAddress(assetData, 1); + + return (proxyId, token); + } } diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index e2c445463..eb23736a0 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -20,14 +20,12 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; -import "../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol"; import "./MixinAssetProxy.sol"; import "./MixinAuthorizable.sol"; import "../../tokens/ERC721Token/ERC721Token.sol"; contract ERC721Proxy is LibBytes, - LibAssetProxyDecoder, MixinAssetProxy, MixinAuthorizable { @@ -56,7 +54,7 @@ contract ERC721Proxy is address token, uint256 tokenId, bytes memory data - ) = decodeERC721Data(assetData); + ) = decodeERC721AssetData(assetData); // Data must be intended for this proxy. uint256 length = assetMetadata.length; @@ -92,4 +90,29 @@ contract ERC721Proxy is { return PROXY_ID; } + + /// @dev Decodes ERC721 Asset Proxy data + function decodeERC721AssetData(bytes memory assetData) + internal + pure + returns ( + uint8 proxyId, + address token, + uint256 tokenId, + bytes memory data + ) + { + require( + assetData.length >= 53, + INVALID_ASSET_DATA_LENGTH + ); + proxyId = uint8(assetData[0]); + token = readAddress(assetData, 1); + tokenId = readUint256(assetData, 21); + if (assetData.length > 53) { + data = readBytes(assetData, 53); + } + + return (proxyId, token, tokenId, data); + } } diff --git a/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol new file mode 100644 index 000000000..45787d88b --- /dev/null +++ b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol @@ -0,0 +1,52 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; +pragma experimental ABIEncoderV2; + +import "../../protocol/AssetProxy/ERC20Proxy.sol"; +import "../../protocol/AssetProxy/ERC721Proxy.sol"; + +contract TestAssetDataDecoders is + ERC20Proxy, + ERC721Proxy +{ + + /// @dev Decodes ERC721 Asset Proxy data + function publicDecodeERC20Data(bytes memory assetData) + public + pure + returns (uint8, address) + { + return ERC20Proxy.decodeERC20AssetData(assetData); + } + + /// @dev Decodes ERC721 Asset Proxy data + function publicDecodeERC721Data(bytes memory assetData) + public + pure + returns ( + uint8, + address, + uint256, + bytes memory + ) + { + return ERC721Proxy.decodeERC721AssetData(assetData); + } +} diff --git a/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol b/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol deleted file mode 100644 index 6d2866656..000000000 --- a/packages/contracts/src/contracts/current/test/TestLibAssetProxyDecoder/TestLibAssetProxyDecoder.sol +++ /dev/null @@ -1,50 +0,0 @@ -/* - - Copyright 2018 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.4.24; -pragma experimental ABIEncoderV2; - -import "../../utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol"; - -contract TestLibAssetProxyDecoder is - LibAssetProxyDecoder -{ - - /// @dev Decodes ERC721 Asset Proxy data - function publicDecodeERC20Data(bytes memory assetData) - public - pure - returns (uint8, address) - { - return decodeERC20Data(assetData); - } - - /// @dev Decodes ERC721 Asset Proxy data - function publicDecodeERC721Data(bytes memory assetData) - public - pure - returns ( - uint8, - address, - uint256, - bytes memory - ) - { - return decodeERC721Data(assetData); - } -} diff --git a/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol b/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol deleted file mode 100644 index ec27502a8..000000000 --- a/packages/contracts/src/contracts/current/utils/LibAssetProxyDecoder/LibAssetProxyDecoder.sol +++ /dev/null @@ -1,74 +0,0 @@ -/* - - Copyright 2018 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.4.24; -pragma experimental ABIEncoderV2; - -import "../LibBytes/LibBytes.sol"; - -contract LibAssetProxyDecoder is - LibBytes -{ - - string constant INVALID_ERC20_METADATA_LENGTH = "Metadata must have a length of 21."; - string constant INVALID_ERC721_METADATA_LENGTH = "Metadata must have a length of at least 53."; - - /// @dev Decodes ERC721 Asset Proxy data - function decodeERC20Data(bytes memory assetData) - internal - pure - returns ( - uint8 proxyId, - address token - ) - { - require( - assetData.length == 21, - INVALID_ERC20_METADATA_LENGTH - ); - proxyId = uint8(assetData[0]); - token = readAddress(assetData, 1); - - return (proxyId, token); - } - - /// @dev Decodes ERC721 Asset Proxy data - function decodeERC721Data(bytes memory assetData) - internal - pure - returns ( - uint8 proxyId, - address token, - uint256 tokenId, - bytes memory data - ) - { - require( - assetData.length >= 53, - INVALID_ERC721_METADATA_LENGTH - ); - proxyId = uint8(assetData[0]); - token = readAddress(assetData, 1); - tokenId = readUint256(assetData, 21); - if (assetData.length > 53) { - data = readBytes(assetData, 53); - } - - return (proxyId, token, tokenId, data); - } -} diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index a1c8483d8..42de7c921 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -11,7 +11,7 @@ import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json'; import * as MultiSigWallet from '../artifacts/MultiSigWallet.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json'; import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json'; -import * as TestLibAssetProxyDecoder from '../artifacts/TestLibAssetProxyDecoder.json'; +import * as TestAssetDataDecoders from '../artifacts/TestAssetDataDecoders.json'; import * as TestLibBytes from '../artifacts/TestLibBytes.json'; import * as TestLibMem from '../artifacts/TestLibMem.json'; import * as TestLibs from '../artifacts/TestLibs.json'; @@ -34,7 +34,7 @@ export const artifacts = { MultiSigWallet: (MultiSigWallet as any) as ContractArtifact, MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact, TestAssetProxyDispatcher: (TestAssetProxyDispatcher as any) as ContractArtifact, - TestLibAssetProxyDecoder: (TestLibAssetProxyDecoder as any) as ContractArtifact, + TestAssetDataDecoders: (TestAssetDataDecoders as any) as ContractArtifact, TestLibBytes: (TestLibBytes as any) as ContractArtifact, TestLibMem: (TestLibMem as any) as ContractArtifact, TestLibs: (TestLibs as any) as ContractArtifact, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index cccca5705..bb8c12088 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -90,7 +90,7 @@ export enum ContractName { AccountLevels = 'AccountLevels', EtherDelta = 'EtherDelta', Arbitrage = 'Arbitrage', - TestLibAssetProxyDecoder = 'TestLibAssetProxyDecoder', + TestAssetDataDecoders = 'TestAssetDataDecoders', TestAssetProxyDispatcher = 'TestAssetProxyDispatcher', TestLibMem = 'TestLibMem', TestLibs = 'TestLibs', diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 712ef8656..8c1253d5c 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -7,12 +7,12 @@ import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); import * as Web3 from 'web3'; -import { TestLibAssetProxyDecoderContract } from '../../src/contract_wrappers/generated/test_lib_asset_proxy_decoder'; +import { TestAssetDataDecodersContract } from '../../src/contract_wrappers/generated/test_asset_data_decoders'; import { artifacts } from '../../src/utils/artifacts'; import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; -import { AssetProxyId, ERC20AssetData, ERC721AssetData, AssetData } from '../../src/utils/types'; +import { AssetData, AssetProxyId, ERC20AssetData, ERC721AssetData } from '../../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); @@ -21,7 +21,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('LibAssetProxyDecoder', () => { let owner: string; - let testAssetProxyDecoder: TestLibAssetProxyDecoderContract; + let testAssetProxyDecoder: TestAssetDataDecodersContract; let testAddress: string; before(async () => { @@ -30,8 +30,8 @@ describe('LibAssetProxyDecoder', () => { owner = accounts[0]; testAddress = accounts[1]; // Deploy TestLibMem - testAssetProxyDecoder = await TestLibAssetProxyDecoderContract.deployFrom0xArtifactAsync( - artifacts.TestLibAssetProxyDecoder, + testAssetProxyDecoder = await TestAssetDataDecodersContract.deployFrom0xArtifactAsync( + artifacts.TestAssetDataDecoders, provider, txDefaults, ); -- cgit v1.2.3 From 05f1e9e3b8f5da593d949a1a18abba70568adb9c Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 31 May 2018 16:49:10 -0700 Subject: Resolved edge case in Memcpy where where send would eventually turn "negative" and wrap around. --- .../src/contracts/current/utils/LibMem/LibMem.sol | 28 ++- packages/contracts/test/libraries/lib_mem.ts | 270 +++++++++++---------- 2 files changed, 154 insertions(+), 144 deletions(-) diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol index f7ff4ca59..500044500 100644 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -19,7 +19,7 @@ pragma solidity ^0.4.24; contract LibMem { - + function getMemAddress(bytes memory input) internal pure @@ -30,7 +30,7 @@ contract LibMem { } return address_; } - + /// @dev Copies `length` bytes from memory location `source` to `dest`. /// @param dest memory address to copy bytes to /// @param source memory address to copy bytes from @@ -58,7 +58,7 @@ contract LibMem { if (source == dest) { return; } - + // For large copies we copy whole words at a time. The final // word is aligned to the end of the range (instead of after the // previous) to handle partial words. So a copy will look like this: @@ -76,6 +76,9 @@ contract LibMem { // if (source > dest) { assembly { + // Record the total number of full words to copy + let nwords := div(length, 32) + // We subtract 32 from `send` and `dend` because it // is easier to compare with in the loop, and these // are also the addresses we need for copying the @@ -83,44 +86,47 @@ contract LibMem { length := sub(length, 32) let send := add(source, length) let dend := add(dest, length) - + // Remember the last 32 bytes of source // This needs to be done here and not after the loop // because we may have overwritten the last bytes in // source already due to overlap. let last := mload(send) - + // Copy whole words front to back - for {} lt(source, send) {} { + for {let i := 0} lt(i, nwords) {i := add(i, 1)} { mstore(dest, mload(source)) source := add(source, 32) dest := add(dest, 32) } - + // Write the last 32 bytes mstore(dend, last) } } else { assembly { + // Record the total number of full words to copy + let nwords := div(length, 32) + // We subtract 32 from `send` and `dend` because those // are the starting points when copying a word at the end. length := sub(length, 32) let send := add(source, length) let dend := add(dest, length) - + // Remember the first 32 bytes of source // This needs to be done here and not after the loop // because we may have overwritten the first bytes in // source already due to overlap. let first := mload(source) - + // Copy whole words back to front - for {} lt(source, send) {} { + for {let i := 0} lt(i, nwords) {i := add(i, 1)} { mstore(dend, mload(send)) send := sub(send, 32) dend := sub(dend, 32) } - + // Write the first 32 bytes mstore(dest, first) } diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 225a8d60d..dd6f46742 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -11,13 +11,11 @@ const expect = chai.expect; // BUG: Ideally we would use Buffer.from(memory).toString('hex') // https://github.com/Microsoft/TypeScript/issues/23155 -const toHex = (buf: Uint8Array): string => - buf.reduce((a, v) => a + ('00' + v.toString(16)).slice(-2), '0x'); +const toHex = (buf: Uint8Array): string => buf.reduce((a, v) => a + ('00' + v.toString(16)).slice(-2), '0x'); -const fromHex = (str: string): Uint8Array => - Uint8Array.from(Buffer.from(str.slice(2), 'hex')); +const fromHex = (str: string): Uint8Array => Uint8Array.from(Buffer.from(str.slice(2), 'hex')); -describe('LibMem', () => { +describe.only('LibMem', () => { let owner: string; let testLibMem: TestLibMemContract; @@ -30,10 +28,9 @@ describe('LibMem', () => { }); describe('memcpy', () => { - // Create memory 0x000102...FF const memSize = 256; - const memory = (new Uint8Array(memSize)).map((_, i) => i); + const memory = new Uint8Array(memSize).map((_, i) => i); const memHex = toHex(memory); // Reference implementation to test against @@ -60,131 +57,138 @@ describe('LibMem', () => { test([[0, 0, 0, 'copies zero bytes with overlap']]); - describe('copies forward', () => test([ - [128, 0, 0, 'zero bytes'], - [128, 0, 1, 'one byte'], - [128, 0, 11, 'eleven bytes'], - [128, 0, 31, 'thirty-one bytes'], - [128, 0, 32, 'one word'], - [128, 0, 64, 'two words'], - [128, 0, 96, 'three words'], - [128, 0, 33, 'one word and one byte'], - [128, 0, 72, 'two words and eight bytes'], - [128, 0, 100, 'three words and four bytes'], - ])); - - describe('copies forward within one word', () => test([ - [16, 0, 0, 'zero bytes'], - [16, 0, 1, 'one byte'], - [16, 0, 11, 'eleven bytes'], - [16, 0, 16, 'sixteen bytes'], - ])); - - describe('copies forward with one byte overlap', () => test([ - [0, 0, 1, 'one byte'], - [10, 0, 11, 'eleven bytes'], - [30, 0, 31, 'thirty-one bytes'], - [31, 0, 32, 'one word'], - [32, 0, 33, 'one word and one byte'], - [71, 0, 72, 'two words and eight bytes'], - [99, 0, 100, 'three words and four bytes'], - ])); - - describe('copies forward with thirty-one bytes overlap', () => test([ - [0, 0, 31, 'thirty-one bytes'], - [1, 0, 32, 'one word'], - [2, 0, 33, 'one word and one byte'], - [41, 0, 72, 'two words and eight bytes'], - [69, 0, 100, 'three words and four bytes'], - ])); - - describe('copies forward with one word overlap', () => test([ - [0, 0, 32, 'one word'], - [1, 0, 33, 'one word and one byte'], - [41, 0, 72, 'two words and eight bytes'], - [69, 0, 100, 'three words and four bytes'], - ])); - - describe('copies forward with one word and one byte overlap', () => test([ - [0, 0, 33, 'one word and one byte'], - [40, 0, 72, 'two words and eight bytes'], - [68, 0, 100, 'three words and four bytes'], - ])); - - describe('copies forward with two words overlap', () => test([ - [0, 0, 64, 'two words'], - [8, 0, 72, 'two words and eight bytes'], - [36, 0, 100, 'three words and four bytes'], - ])); - - describe('copies forward within one word and one byte overlap', () => test([ - [0, 0, 1, 'one byte'], - [10, 0, 11, 'eleven bytes'], - [15, 0, 16, 'sixteen bytes'], - ])); - - describe('copies backward', () => test([ - [0, 128, 0, 'zero bytes'], - [0, 128, 1, 'one byte'], - [0, 128, 11, 'eleven bytes'], - [0, 128, 31, 'thirty-one bytes'], - [0, 128, 32, 'one word'], - [0, 128, 64, 'two words'], - [0, 128, 96, 'three words'], - [0, 128, 33, 'one word and one byte'], - [0, 128, 72, 'two words and eight bytes'], - [0, 128, 100, 'three words and four bytes'], - ])); - - describe('copies backward within one word', () => test([ - [0, 16, 0, 'zero bytes'], - [0, 16, 1, 'one byte'], - [0, 16, 11, 'eleven bytes'], - [0, 16, 16, 'sixteen bytes'], - ])); - - describe('copies backward with one byte overlap', () => test([ - [0, 0, 1, 'one byte'], - [0, 10, 11, 'eleven bytes'], - [0, 30, 31, 'thirty-one bytes'], - [0, 31, 32, 'one word'], - [0, 32, 33, 'one word and one byte'], - [0, 71, 72, 'two words and eight bytes'], - [0, 99, 100, 'three words and four bytes'], - ])); - - describe('copies backward with thirty-one bytes overlap', () => test([ - [0, 0, 31, 'thirty-one bytes'], - [0, 1, 32, 'one word'], - [0, 2, 33, 'one word and one byte'], - [0, 41, 72, 'two words and eight bytes'], - [0, 69, 100, 'three words and four bytes'], - ])); - - describe('copies backward with one word overlap', () => test([ - [0, 0, 32, 'one word'], - [0, 1, 33, 'one word and one byte'], - [0, 41, 72, 'two words and eight bytes'], - [0, 69, 100, 'three words and four bytes'], - ])); - - describe('copies backward with one word and one byte overlap', () => test([ - [0, 0, 33, 'one word and one byte'], - [0, 40, 72, 'two words and eight bytes'], - [0, 68, 100, 'three words and four bytes'], - ])); - - describe('copies backward with two words overlap', () => test([ - [0, 0, 64, 'two words'], - [0, 8, 72, 'two words and eight bytes'], - [0, 36, 100, 'three words and four bytes'], - ])); - - describe('copies forward within one word and one byte overlap', () => test([ - [0, 0, 1, 'one byte'], - [0, 10, 11, 'eleven bytes'], - [0, 15, 16, 'sixteen bytes'], - ])); - + describe('copies forward', () => + test([ + [128, 0, 0, 'zero bytes'], + [128, 0, 1, 'one byte'], + [128, 0, 11, 'eleven bytes'], + [128, 0, 31, 'thirty-one bytes'], + [128, 0, 32, 'one word'], + [128, 0, 64, 'two words'], + [128, 0, 96, 'three words'], + [128, 0, 33, 'one word and one byte'], + [128, 0, 72, 'two words and eight bytes'], + [128, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward within one word', () => + test([ + [16, 0, 0, 'zero bytes'], + [16, 0, 1, 'one byte'], + [16, 0, 11, 'eleven bytes'], + [16, 0, 16, 'sixteen bytes'], + ])); + + describe('copies forward with one byte overlap', () => + test([ + [0, 0, 1, 'one byte'], + [10, 0, 11, 'eleven bytes'], + [30, 0, 31, 'thirty-one bytes'], + [31, 0, 32, 'one word'], + [32, 0, 33, 'one word and one byte'], + [71, 0, 72, 'two words and eight bytes'], + [99, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with thirty-one bytes overlap', () => + test([ + [0, 0, 31, 'thirty-one bytes'], + [1, 0, 32, 'one word'], + [2, 0, 33, 'one word and one byte'], + [41, 0, 72, 'two words and eight bytes'], + [69, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with one word overlap', () => + test([ + [0, 0, 32, 'one word'], + [1, 0, 33, 'one word and one byte'], + [41, 0, 72, 'two words and eight bytes'], + [69, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with one word and one byte overlap', () => + test([ + [0, 0, 33, 'one word and one byte'], + [40, 0, 72, 'two words and eight bytes'], + [68, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward with two words overlap', () => + test([ + [0, 0, 64, 'two words'], + [8, 0, 72, 'two words and eight bytes'], + [36, 0, 100, 'three words and four bytes'], + ])); + + describe('copies forward within one word and one byte overlap', () => + test([[0, 0, 1, 'one byte'], [10, 0, 11, 'eleven bytes'], [15, 0, 16, 'sixteen bytes']])); + + describe('copies backward', () => + test([ + [0, 128, 0, 'zero bytes'], + [0, 128, 1, 'one byte'], + [0, 128, 11, 'eleven bytes'], + [0, 128, 31, 'thirty-one bytes'], + [0, 128, 32, 'one word'], + [0, 128, 64, 'two words'], + [0, 128, 96, 'three words'], + [0, 128, 33, 'one word and one byte'], + [0, 128, 72, 'two words and eight bytes'], + [0, 128, 100, 'three words and four bytes'], + ])); + + describe('copies backward within one word', () => + test([ + [0, 16, 0, 'zero bytes'], + [0, 16, 1, 'one byte'], + [0, 16, 11, 'eleven bytes'], + [0, 16, 16, 'sixteen bytes'], + ])); + + describe('copies backward with one byte overlap', () => + test([ + [0, 0, 1, 'one byte'], + [0, 10, 11, 'eleven bytes'], + [0, 30, 31, 'thirty-one bytes'], + [0, 31, 32, 'one word'], + [0, 32, 33, 'one word and one byte'], + [0, 71, 72, 'two words and eight bytes'], + [0, 99, 100, 'three words and four bytes'], + ])); + + describe('copies backward with thirty-one bytes overlap', () => + test([ + [0, 0, 31, 'thirty-one bytes'], + [0, 1, 32, 'one word'], + [0, 2, 33, 'one word and one byte'], + [0, 41, 72, 'two words and eight bytes'], + [0, 69, 100, 'three words and four bytes'], + ])); + + describe('copies backward with one word overlap', () => + test([ + [0, 0, 32, 'one word'], + [0, 1, 33, 'one word and one byte'], + [0, 41, 72, 'two words and eight bytes'], + [0, 69, 100, 'three words and four bytes'], + ])); + + describe('copies backward with one word and one byte overlap', () => + test([ + [0, 0, 33, 'one word and one byte'], + [0, 40, 72, 'two words and eight bytes'], + [0, 68, 100, 'three words and four bytes'], + ])); + + describe('copies backward with two words overlap', () => + test([ + [0, 0, 64, 'two words'], + [0, 8, 72, 'two words and eight bytes'], + [0, 36, 100, 'three words and four bytes'], + ])); + + describe('copies forward within one word and one byte overlap', () => + test([[0, 0, 1, 'one byte'], [0, 10, 11, 'eleven bytes'], [0, 15, 16, 'sixteen bytes']])); }); }); -- cgit v1.2.3 From 3c3851c221873baf3b7fec7213324dae0c1c3351 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 31 May 2018 17:49:12 -0700 Subject: Fixed formatting in memory layout --- .../current/protocol/Exchange/MixinWrapperFunctions.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index 0d9888703..f4822e814 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -91,12 +91,12 @@ contract MixinWrapperFunctions is // | | 0x0E0 | | 8. takerFeeAmount | // | | 0x100 | | 9. expirationTimeSeconds | // | | 0x120 | | 10. salt | - // | | 0x140 | | 11. Offset to makerAssetData (*) | - // | | 0x160 | | 12. Offset to takerAssetData (*) | - // | | 0x180 | 32 | makerAssetData Length | - // | | 0x1A0 | ** | makerAssetData Contents | - // | | 0x1C0 | 32 | takerAssetData Length | - // | | 0x1E0 | ** | takerAssetData Contents | + // | | 0x140 | | 11. Offset to makerAssetData (*) | + // | | 0x160 | | 12. Offset to takerAssetData (*) | + // | | 0x180 | 32 | makerAssetData Length | + // | | 0x1A0 | ** | makerAssetData Contents | + // | | 0x1C0 | 32 | takerAssetData Length | + // | | 0x1E0 | ** | takerAssetData Contents | // | | 0x200 | 32 | signature Length | // | | 0x220 | ** | signature Contents | -- cgit v1.2.3 From 8496c1cdd3bc477fcfe584adf8200f4ed35da2b0 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 31 May 2018 18:59:02 -0700 Subject: Call safeTransferFrom only when there is receiver data present --- .../current/protocol/AssetProxy/ERC721Proxy.sol | 7 ++++++- packages/contracts/test/asset_proxy/proxies.ts | 24 ++++++++++++---------- packages/contracts/test/libraries/lib_mem.ts | 2 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index eb23736a0..9dac02d87 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -77,8 +77,13 @@ contract ERC721Proxy is ); // Transfer token. + // Save gas by calling safeTransferFrom only when there is data present. // Either succeeds or throws. - ERC721Token(token).safeTransferFrom(from, to, tokenId, data); + if(data.length > 0) { + ERC721Token(token).safeTransferFrom(from, to, tokenId, data); + } else { + ERC721Token(token).transferFrom(from, to, tokenId); + } } /// @dev Gets the proxy id associated with the proxy address. diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index d6bc8163b..f44c44045 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -280,7 +280,7 @@ describe('Asset Transfer Proxies', () => { expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress); }); - it('should call onERC721Received when transferring to a smart contract', async () => { + it('should not call onERC721Received when transferring to a smart contract without receiver data', async () => { // Construct metadata for ERC721 proxy const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition @@ -296,23 +296,20 @@ describe('Asset Transfer Proxies', () => { amount, { from: exchangeAddress }, ); + // Parse transaction logs const tx = await zeroEx.awaitTransactionMinedAsync(txHash); tx.logs = _.filter(tx.logs, log => log.address === erc721Receiver.address); const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log)); - // Validate log emitted by erc721 receiver - expect(tx.logs.length).to.be.equal(1); - const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs; - expect(tokenReceivedLog.args.from).to.be.equal(makerAddress); - expect(tokenReceivedLog.args.tokenId).to.be.bignumber.equal(erc721MakerTokenId); - expect(tokenReceivedLog.args.data).to.be.equal(nullDataHex); + // Verify that no log was emitted by erc721 receiver + expect(tx.logs.length).to.be.equal(0); // Verify transfer was successful const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address); }); - it('should call onERC721Received when transferring to a smart contract and receive extra data', async () => { + it('should call onERC721Received when transferring to a smart contract with receiver data', async () => { // Construct metadata for ERC721 proxy const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); const encodedAssetData = assetProxyUtils.encodeERC721AssetData( @@ -338,7 +335,7 @@ describe('Asset Transfer Proxies', () => { tx.logs = _.filter(tx.logs, log => log.address === erc721Receiver.address); const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log)); - // Validate log emitted by erc721 receiver + // Validate log emitted by erc721 receiver expect(tx.logs.length).to.be.equal(1); const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs; expect(tokenReceivedLog.args.from).to.be.equal(makerAddress); @@ -349,9 +346,14 @@ describe('Asset Transfer Proxies', () => { expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address); }); - it('should throw if receiving contract does not have onERC721Received', async () => { + it('should throw if there is receiver data but contract does not have onERC721Received', async () => { // Construct metadata for ERC721 proxy - const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); + const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); + const encodedAssetData = assetProxyUtils.encodeERC721AssetData( + erc721Token.address, + erc721MakerTokenId, + data, + ); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index dd6f46742..efe719255 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -15,7 +15,7 @@ const toHex = (buf: Uint8Array): string => buf.reduce((a, v) => a + ('00' + v.to const fromHex = (str: string): Uint8Array => Uint8Array.from(Buffer.from(str.slice(2), 'hex')); -describe.only('LibMem', () => { +describe('LibMem', () => { let owner: string; let testLibMem: TestLibMemContract; -- cgit v1.2.3 From f03e5c6bd12c88fffbad324fd7493d3acedea0aa Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 1 Jun 2018 11:34:45 -0700 Subject: Style audit proxies --- .../current/protocol/AssetProxy/ERC20Proxy.sol | 8 +++- .../current/protocol/AssetProxy/ERC721Proxy.sol | 33 ++++++++++++----- .../TestAssetDataDecoders.sol | 43 +++++++++++++++++----- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 11383adaf..54cbeb963 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -79,7 +79,10 @@ contract ERC20Proxy is return PROXY_ID; } - /// @dev Decodes ERC20 Asset Proxy data + /// @dev Decodes ERC20 Asset data. + /// @param assetData Encoded byte array. + /// @return proxyId Intended ERC20 proxy id. + /// @return token ERC20 token address. function decodeERC20AssetData(bytes memory assetData) internal pure @@ -88,10 +91,13 @@ contract ERC20Proxy is address token ) { + // Validate encoded data length require( assetData.length == 21, INVALID_ASSET_DATA_LENGTH ); + + // Decode data proxyId = uint8(assetData[0]); token = readAddress(assetData, 1); diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 9dac02d87..58c23b03b 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -53,7 +53,7 @@ contract ERC721Proxy is uint8 proxyId, address token, uint256 tokenId, - bytes memory data + bytes memory receiverData ) = decodeERC721AssetData(assetData); // Data must be intended for this proxy. @@ -76,11 +76,10 @@ contract ERC721Proxy is INVALID_AMOUNT ); - // Transfer token. - // Save gas by calling safeTransferFrom only when there is data present. - // Either succeeds or throws. - if(data.length > 0) { - ERC721Token(token).safeTransferFrom(from, to, tokenId, data); + // Transfer token. Saves gas by calling safeTransferFrom only + // when there is receiverData present. Either succeeds or throws. + if(receiverData.length > 0) { + ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData); } else { ERC721Token(token).transferFrom(from, to, tokenId); } @@ -96,7 +95,13 @@ contract ERC721Proxy is return PROXY_ID; } - /// @dev Decodes ERC721 Asset Proxy data + /// @dev Decodes ERC721 Asset data. + /// @param assetData Encoded byte array. + /// @return proxyId Intended ERC721 proxy id. + /// @return token ERC721 token address. + /// @return tokenId ERC721 token id. + /// @return receiverData Additional data with no specific format, which + /// is passed to the receiving contract's onERC721Received. function decodeERC721AssetData(bytes memory assetData) internal pure @@ -104,20 +109,28 @@ contract ERC721Proxy is uint8 proxyId, address token, uint256 tokenId, - bytes memory data + bytes memory receiverData ) { + // Validate encoded data length require( assetData.length >= 53, INVALID_ASSET_DATA_LENGTH ); + + // Decode asset data proxyId = uint8(assetData[0]); token = readAddress(assetData, 1); tokenId = readUint256(assetData, 21); if (assetData.length > 53) { - data = readBytes(assetData, 53); + receiverData = readBytes(assetData, 53); } - return (proxyId, token, tokenId, data); + return ( + proxyId, + token, + tokenId, + receiverData + ); } } diff --git a/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol index 45787d88b..2c6a8fdb0 100644 --- a/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol +++ b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol @@ -27,26 +27,51 @@ contract TestAssetDataDecoders is ERC721Proxy { - /// @dev Decodes ERC721 Asset Proxy data + /// @dev Decodes ERC20 Asset data. + /// @param assetData Encoded byte array. + /// @return proxyId Intended ERC20 proxy id. + /// @return token ERC20 token address. function publicDecodeERC20Data(bytes memory assetData) public pure - returns (uint8, address) + returns ( + uint8 proxyId, + address token + ) { - return ERC20Proxy.decodeERC20AssetData(assetData); + (proxyId, token) = decodeERC20AssetData(assetData); + return (proxyId, token); } - /// @dev Decodes ERC721 Asset Proxy data + /// @dev Decodes ERC721 Asset data. + /// @param assetData Encoded byte array. + /// @return proxyId Intended ERC721 proxy id. + /// @return token ERC721 token address. + /// @return tokenId ERC721 token id. + /// @return receiverData Additional data with no specific format, which + /// is passed to the receiving contract's onERC721Received. function publicDecodeERC721Data(bytes memory assetData) public pure returns ( - uint8, - address, - uint256, - bytes memory + uint8 proxyId, + address token, + uint256 tokenId, + bytes memory receiverData ) { - return ERC721Proxy.decodeERC721AssetData(assetData); + ( + proxyId, + token, + tokenId, + receiverData + ) = decodeERC721AssetData(assetData); + + return ( + proxyId, + token, + tokenId, + receiverData + ); } } -- cgit v1.2.3 From 3ed13150e106c19563c8e9b06621be3d44d66b6c Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 1 Jun 2018 11:54:20 -0700 Subject: Style audit for proxies + libmem + libbytes --- .../current/protocol/AssetProxy/ERC20Proxy.sol | 2 +- .../current/protocol/AssetProxy/ERC721Proxy.sol | 4 +-- .../current/test/TestLibBytes/TestLibBytes.sol | 11 +++++-- .../current/test/TestLibMem/TestLibMem.sol | 15 ++++++--- .../contracts/current/utils/LibBytes/LibBytes.sol | 13 ++++---- .../src/contracts/current/utils/LibMem/LibMem.sol | 18 ++++++---- packages/contracts/test/asset_proxy/decoder.ts | 21 ++++++------ packages/contracts/test/asset_proxy/proxies.ts | 38 ++++++++++++---------- 8 files changed, 72 insertions(+), 50 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 54cbeb963..96950f1cd 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -47,7 +47,7 @@ contract ERC20Proxy is ) internal { - // Decode proxy data. + // Decode asset data. ( uint8 proxyId, address token diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 58c23b03b..102064c15 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -48,7 +48,7 @@ contract ERC721Proxy is ) internal { - // Decode proxy data. + // Decode asset data. ( uint8 proxyId, address token, @@ -118,7 +118,7 @@ contract ERC721Proxy is INVALID_ASSET_DATA_LENGTH ); - // Decode asset data + // Decode asset data. proxyId = uint8(assetData[0]); token = readAddress(assetData, 1); tokenId = readUint256(assetData, 21); diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 0bf11b03b..f009a6a71 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -155,7 +155,6 @@ contract TestLibBytes is return b; } -======= /// @dev Reads the first 4 bytes from a byte array of arbitrary length. /// @param b Byte array to read first 4 bytes from. /// @return First 4 bytes of data. @@ -168,6 +167,10 @@ contract TestLibBytes is return result; } + /// @dev Reads nested bytes from a specific position. + /// @param b Byte array containing nested bytes. + /// @param index Index of nested bytes. + /// @return result Nested bytes. function publicReadBytes( bytes memory b, uint256 index) @@ -179,7 +182,11 @@ contract TestLibBytes is return result; } - + /// @dev Inserts bytes at a specific position in a byte array. + /// @param b Byte array to insert into. + /// @param index Index in byte array of . + /// @param input bytes to insert. + /// @return b Updated input byte array function publicWriteBytes( bytes memory b, uint256 index, diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol index 64bc182f4..076bee24c 100644 --- a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol +++ b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol @@ -23,8 +23,15 @@ import "../../utils/LibMem/LibMem.sol"; contract TestLibMem is LibMem { + + /// @dev Copies a block of memory from one location to another. + /// @param mem Memory contents we want to apply memcpy to + /// @param dest Destination offset into . + /// @param source Source offset into . + /// @param length Length of bytes to copy from to + /// @return mem Memory contents after calling memcpy. function testMemcpy( - bytes mem, ///< Memory contents we want to apply memcpy to + bytes mem, uint256 dest, uint256 source, uint256 length @@ -36,13 +43,13 @@ contract TestLibMem is // Sanity check. Overflows are not checked. require(source + length <= mem.length); require(dest + length <= mem.length); - + // Get pointer to memory contents uint256 offset = getMemAddress(mem) + 32; - + // Execute memcpy adjusted for memory array location memcpy(offset + dest, offset + source, length); - + // Return modified memory contents return mem; } diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 6351f1a46..5610c47b3 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -268,7 +268,6 @@ contract LibBytes is writeBytes32(b, index, bytes32(input)); } -======= /// @dev Reads the first 4 bytes from a byte array of arbitrary length. /// @param b Byte array to read first 4 bytes from. /// @return First 4 bytes of data. @@ -287,10 +286,10 @@ contract LibBytes is return result; } - /// @dev Reads a uint256 value from a position in a byte array. - /// @param b Byte array containing a uint256 value. - /// @param index Index in byte array of uint256 value. - /// @return uint256 value from byte array. + /// @dev Reads nested bytes from a specific position. + /// @param b Byte array containing nested bytes. + /// @param index Index of nested bytes. + /// @return result Nested bytes. function readBytes( bytes memory b, uint256 index @@ -321,10 +320,10 @@ contract LibBytes is return result; } - /// @dev Writes a uint256 into a specific position in a byte array. + /// @dev Inserts bytes at a specific position in a byte array. /// @param b Byte array to insert into. /// @param index Index in byte array of . - /// @param input uint256 to put into byte array. + /// @param input bytes to insert. function writeBytes( bytes memory b, uint256 index, diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol index 500044500..960850725 100644 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -18,23 +18,27 @@ pragma solidity ^0.4.24; -contract LibMem { +contract LibMem +{ + /// @dev Gets the memory address for a byte array. + /// @param input Byte array to lookup. + /// @return memoryAddress Memory address of byte array. function getMemAddress(bytes memory input) internal pure - returns (uint256 address_) + returns (uint256 memoryAddress) { assembly { - address_ := input + memoryAddress := input } - return address_; + return memoryAddress; } /// @dev Copies `length` bytes from memory location `source` to `dest`. - /// @param dest memory address to copy bytes to - /// @param source memory address to copy bytes from - /// @param length number of bytes to copy + /// @param dest memory address to copy bytes to. + /// @param source memory address to copy bytes from. + /// @param length number of bytes to copy. function memcpy( uint256 dest, uint256 source, diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 8c1253d5c..e395c04c1 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -19,7 +19,7 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -describe('LibAssetProxyDecoder', () => { +describe('TestAssetDataDecoders', () => { let owner: string; let testAssetProxyDecoder: TestAssetDataDecodersContract; let testAddress: string; @@ -43,8 +43,8 @@ describe('LibAssetProxyDecoder', () => { await blockchainLifecycle.revertAsync(); }); - describe('LibAssetProxyDecoder', () => { - it('should correctly decode ERC20 proxy data)', async () => { + describe('Asset Data Decoders', () => { + it('should correctly decode ERC20 asset data)', async () => { const encodedAssetData = assetProxyUtils.encodeERC20AssetData(testAddress); const expectedDecodedAssetData = assetProxyUtils.decodeERC20AssetData(encodedAssetData); let decodedAssetProxyId: number; @@ -56,7 +56,7 @@ describe('LibAssetProxyDecoder', () => { expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress); }); - it('should correctly decode ERC721 proxy data', async () => { + it('should correctly decode ERC721 asset data', async () => { const tokenId = ZeroEx.generatePseudoRandomSalt(); const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId); const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData); @@ -76,25 +76,26 @@ describe('LibAssetProxyDecoder', () => { expect(decodedData).to.be.equal(expectedDecodedAssetData.data); }); - it('should correctly decode ERC721 proxy data with receiver data', async () => { + it('should correctly decode ERC721 asset data with receiver data', async () => { const tokenId = ZeroEx.generatePseudoRandomSalt(); - const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())) + 'FFFF'; - const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId, data); + const receiverData = + ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())) + 'FFFF'; + const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId, receiverData); const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData); let decodedAssetProxyId: number; let decodedTokenAddress: string; let decodedTokenId: BigNumber; - let decodedData: string; + let decodedReceiverData: string; [ decodedAssetProxyId, decodedTokenAddress, decodedTokenId, - decodedData, + decodedReceiverData, ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedAssetData); expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId); expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress); expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedAssetData.tokenId); - expect(decodedData).to.be.equal(expectedDecodedAssetData.data); + expect(decodedReceiverData).to.be.equal(expectedDecodedAssetData.data); }); }); }); diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index f44c44045..e8c598935 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -106,7 +106,7 @@ describe('Asset Transfer Proxies', () => { describe('Transfer Proxy - ERC20', () => { describe('transferFrom', () => { it('should successfully transfer tokens', async () => { - // Construct metadata for ERC20 proxy + // Construct ERC20 asset data const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); @@ -132,7 +132,7 @@ describe('Asset Transfer Proxies', () => { }); it('should do nothing if transferring 0 amount of a token', async () => { - // Construct metadata for ERC20 proxy + // Construct ERC20 asset data const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); @@ -158,7 +158,7 @@ describe('Asset Transfer Proxies', () => { }); it('should throw if allowances are too low', async () => { - // Construct metadata for ERC20 proxy + // Construct ERC20 asset data const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Create allowance less than transfer amount. Set allowance on proxy. const allowance = new BigNumber(0); @@ -182,7 +182,7 @@ describe('Asset Transfer Proxies', () => { }); it('should throw if requesting address is not authorized', async () => { - // Construct metadata for ERC20 proxy + // Construct ERC20 asset data const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(10); @@ -258,7 +258,7 @@ describe('Asset Transfer Proxies', () => { describe('Transfer Proxy - ERC721', () => { describe('transferFrom', () => { it('should successfully transfer tokens', async () => { - // Construct metadata for ERC721 proxy + // Construct ERC721 asset data const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -281,7 +281,7 @@ describe('Asset Transfer Proxies', () => { }); it('should not call onERC721Received when transferring to a smart contract without receiver data', async () => { - // Construct metadata for ERC721 proxy + // Construct ERC721 asset data const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -310,12 +310,14 @@ describe('Asset Transfer Proxies', () => { }); it('should call onERC721Received when transferring to a smart contract with receiver data', async () => { - // Construct metadata for ERC721 proxy - const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); + // Construct ERC721 asset data + const receiverData = ethUtil.bufferToHex( + assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt()), + ); const encodedAssetData = assetProxyUtils.encodeERC721AssetData( erc721Token.address, erc721MakerTokenId, - data, + receiverData, ); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -340,19 +342,21 @@ describe('Asset Transfer Proxies', () => { const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs; expect(tokenReceivedLog.args.from).to.be.equal(makerAddress); expect(tokenReceivedLog.args.tokenId).to.be.bignumber.equal(erc721MakerTokenId); - expect(tokenReceivedLog.args.data).to.be.equal(data); + expect(tokenReceivedLog.args.data).to.be.equal(receiverData); // Verify transfer was successful const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address); }); it('should throw if there is receiver data but contract does not have onERC721Received', async () => { - // Construct metadata for ERC721 proxy - const data = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); + // Construct ERC721 asset data + const receiverData = ethUtil.bufferToHex( + assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt()), + ); const encodedAssetData = assetProxyUtils.encodeERC721AssetData( erc721Token.address, erc721MakerTokenId, - data, + receiverData, ); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -372,7 +376,7 @@ describe('Asset Transfer Proxies', () => { }); it('should throw if transferring 0 amount of a token', async () => { - // Construct metadata for ERC721 proxy + // Construct ERC721 asset data const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -391,7 +395,7 @@ describe('Asset Transfer Proxies', () => { }); it('should throw if transferring > 1 amount of a token', async () => { - // Construct metadata for ERC721 proxy + // Construct ERC721 asset data const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); @@ -410,7 +414,7 @@ describe('Asset Transfer Proxies', () => { }); it('should throw if allowances are too low', async () => { - // Construct metadata for ERC721 proxy + // Construct ERC721 asset data const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Remove transfer approval for makerAddress. await web3Wrapper.awaitTransactionSuccessAsync( @@ -429,7 +433,7 @@ describe('Asset Transfer Proxies', () => { }); it('should throw if requesting address is not authorized', async () => { - // Construct metadata for ERC721 proxy + // Construct ERC721 asset data const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(1); -- cgit v1.2.3 From e4e36760952287a84f8991df8589c183036383db Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 1 Jun 2018 14:17:13 -0700 Subject: Fixed up after rebasing. Contracts build and tests pass --- .../current/protocol/AssetProxy/ERC20Proxy.sol | 7 ++--- .../current/protocol/AssetProxy/ERC721Proxy.sol | 18 ++++-------- packages/contracts/test/asset_proxy/decoder.ts | 9 +++--- packages/contracts/test/asset_proxy/proxies.ts | 33 ++++++---------------- packages/contracts/test/exchange/core.ts | 4 +-- packages/contracts/test/exchange/transactions.ts | 4 +-- packages/contracts/test/libraries/lib_bytes.ts | 5 ++-- packages/order-utils/src/asset_proxy_utils.ts | 7 +++-- 8 files changed, 34 insertions(+), 53 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 96950f1cd..4e9ae64f8 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -54,8 +54,6 @@ contract ERC20Proxy is ) = decodeERC20AssetData(assetData); // Data must be intended for this proxy. - uint256 length = assetMetadata.length; - require( proxyId == PROXY_ID, PROXY_ID_MISMATCH @@ -92,14 +90,15 @@ contract ERC20Proxy is ) { // Validate encoded data length + uint256 length = assetData.length; require( assetData.length == 21, INVALID_ASSET_DATA_LENGTH ); // Decode data - proxyId = uint8(assetData[0]); - token = readAddress(assetData, 1); + token = readAddress(assetData, 0); + proxyId = uint8(assetData[length-1]); return (proxyId, token); } diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 102064c15..f6c3af104 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -56,15 +56,8 @@ contract ERC721Proxy is bytes memory receiverData ) = decodeERC721AssetData(assetData); - // Data must be intended for this proxy. - uint256 length = assetMetadata.length; - require( - length == 53, - LENGTH_53_REQUIRED - ); - - // TODO: Is this too inflexible in the future? + // Data must be intended for this proxy. require( proxyId == PROXY_ID, PROXY_ID_MISMATCH @@ -113,18 +106,19 @@ contract ERC721Proxy is ) { // Validate encoded data length + uint256 length = assetData.length; require( assetData.length >= 53, INVALID_ASSET_DATA_LENGTH ); // Decode asset data. - proxyId = uint8(assetData[0]); - token = readAddress(assetData, 1); - tokenId = readUint256(assetData, 21); + token = readAddress(assetData, 0); + tokenId = readUint256(assetData, 20); if (assetData.length > 53) { - receiverData = readBytes(assetData, 53); + receiverData = readBytes(assetData, 52); } + proxyId = uint8(assetData[length-1]); return ( proxyId, diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index e395c04c1..6336f69ae 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -1,9 +1,10 @@ -import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import BN = require('bn.js'); import * as chai from 'chai'; +import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import ethUtil = require('ethereumjs-util'); import * as Web3 from 'web3'; @@ -57,7 +58,7 @@ describe('TestAssetDataDecoders', () => { }); it('should correctly decode ERC721 asset data', async () => { - const tokenId = ZeroEx.generatePseudoRandomSalt(); + const tokenId = generatePseudoRandomSalt(); const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId); const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData); let decodedAssetProxyId: number; @@ -77,9 +78,9 @@ describe('TestAssetDataDecoders', () => { }); it('should correctly decode ERC721 asset data with receiver data', async () => { - const tokenId = ZeroEx.generatePseudoRandomSalt(); + const tokenId = generatePseudoRandomSalt(); const receiverData = - ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())) + 'FFFF'; + ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt())) + 'FFFF'; const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId, receiverData); const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData); let decodedAssetProxyId: number; diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index e8c598935..6dc652383 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -1,8 +1,10 @@ -import { LogWithDecodedArgs, ZeroEx } from '0x.js'; import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { assetProxyUtils } from '@0xproject/order-utils'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; +import { LogWithDecodedArgs } from 'ethereum-types'; import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; @@ -82,20 +84,11 @@ describe('Asset Transfer Proxies', () => { }), constants.AWAIT_TRANSACTION_MINED_MS, ); - - await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, { - from: owner, - }); - erc721Receiver = await DummyERC721ReceiverContract.deployFrom0xArtifactAsync( artifacts.DummyERC721Receiver, provider, txDefaults, ); - - zeroEx = new ZeroEx(provider, { - networkId: constants.TESTRPC_NETWORK_ID, - }); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -298,10 +291,8 @@ describe('Asset Transfer Proxies', () => { ); // Parse transaction logs - const tx = await zeroEx.awaitTransactionMinedAsync(txHash); - tx.logs = _.filter(tx.logs, log => log.address === erc721Receiver.address); - const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); - tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log)); + const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address); + const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash); // Verify that no log was emitted by erc721 receiver expect(tx.logs.length).to.be.equal(0); // Verify transfer was successful @@ -311,9 +302,7 @@ describe('Asset Transfer Proxies', () => { it('should call onERC721Received when transferring to a smart contract with receiver data', async () => { // Construct ERC721 asset data - const receiverData = ethUtil.bufferToHex( - assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt()), - ); + const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt())); const encodedAssetData = assetProxyUtils.encodeERC721AssetData( erc721Token.address, erc721MakerTokenId, @@ -333,10 +322,8 @@ describe('Asset Transfer Proxies', () => { { from: exchangeAddress }, ); // Parse transaction logs - const tx = await zeroEx.awaitTransactionMinedAsync(txHash); - tx.logs = _.filter(tx.logs, log => log.address === erc721Receiver.address); - const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID); - tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log)); + const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address); + const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash); // Validate log emitted by erc721 receiver expect(tx.logs.length).to.be.equal(1); const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs; @@ -350,9 +337,7 @@ describe('Asset Transfer Proxies', () => { it('should throw if there is receiver data but contract does not have onERC721Received', async () => { // Construct ERC721 asset data - const receiverData = ethUtil.bufferToHex( - assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt()), - ); + const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt())); const encodedAssetData = assetProxyUtils.encodeERC721AssetData( erc721Token.address, erc721MakerTokenId, diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index 8d3c3a940..53b98c755 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -845,7 +845,7 @@ describe('Exchange core', () => { const makerAssetId = erc721MakerAssetIds[0]; signedOrder = orderFactory.newSignedOrder({ makerAssetAmount: new BigNumber(1), - takerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress), }); @@ -885,7 +885,7 @@ describe('Exchange core', () => { const takerAssetId = erc721TakerAssetIds[0]; signedOrder = orderFactory.newSignedOrder({ takerAssetAmount: new BigNumber(1), - makerAssetAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress), }); diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts index 8c5bc7bec..12390ce01 100644 --- a/packages/contracts/test/exchange/transactions.ts +++ b/packages/contracts/test/exchange/transactions.ts @@ -224,8 +224,8 @@ describe('Exchange transactions', () => { exchangeAddress: exchange.address, makerAddress, feeRecipientAddress, - makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerTokenAddress), - takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerTokenAddress), + makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerTokenAddress), + takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerTokenAddress), }; whitelistOrderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams); }); diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 9fe3a1a57..1a23483ba 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -1,4 +1,6 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import BN = require('bn.js'); import * as chai from 'chai'; @@ -66,7 +68,7 @@ describe('LibBytes', () => { shortTestBytesAsBuffer = Buffer.concat([encodedShortDataLength, encodedShortData]); shortTestBytes = ethUtil.bufferToHex(shortTestBytesAsBuffer); // Create test bytes one word in length - wordOfData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(ZeroEx.generatePseudoRandomSalt())); + wordOfData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt())); const encodedWordOfData = ethUtil.toBuffer(wordOfData); const wordOfDataLength = new BigNumber(encodedWordOfData.byteLength); const encodedWordOfDataLength = assetProxyUtils.encodeUint256(wordOfDataLength); @@ -315,7 +317,6 @@ describe('LibBytes', () => { }); */ -======= describe('readFirst4', () => { // AssertionError: expected promise to be rejected with an error including 'revert' but it was fulfilled with '0x08c379a0' it('should revert if byte array has a length < 4', async () => { diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index 1f1e49f0f..a12be83a3 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -79,13 +79,14 @@ export const assetProxyUtils = { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC721); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); const encodedTokenId = assetProxyUtils.encodeUint256(tokenId); - const encodedMetadata = Buffer.concat([encodedAddress, encodedTokenId, encodedAssetProxyId]); + let encodedMetadata = Buffer.concat([encodedAddress, encodedTokenId]); if (!_.isUndefined(data)) { const encodedData = ethUtil.toBuffer(data); const dataLength = new BigNumber(encodedData.byteLength); const encodedDataLength = assetProxyUtils.encodeUint256(dataLength); encodedMetadata = Buffer.concat([encodedMetadata, encodedDataLength, encodedData]); } + encodedMetadata = Buffer.concat([encodedMetadata, encodedAssetProxyId]); const encodedMetadataHex = ethUtil.bufferToHex(encodedMetadata); return encodedMetadataHex; }, @@ -116,7 +117,7 @@ export const assetProxyUtils = { const nullData = '0x'; let data = nullData; if (encodedAssetData.byteLength > 53) { - const encodedDataLength = encodedAssetData.slice(53, 85); + const encodedDataLength = encodedAssetData.slice(52, 84); const dataLength = assetProxyUtils.decodeUint256(encodedDataLength); const expectedDataLength = new BigNumber(encodedAssetData.byteLength - 85); if (!dataLength.equals(expectedDataLength)) { @@ -124,7 +125,7 @@ export const assetProxyUtils = { `Data length (${dataLength}) does not match actual length of data (${expectedDataLength})`, ); } - const encodedData = encodedAssetData.slice(85); + const encodedData = encodedAssetData.slice(84, expectedDataLength.toNumber() + 84); data = ethUtil.bufferToHex(encodedData); } const erc721AssetData: ERC721AssetData = { -- cgit v1.2.3 From 6e5abade3cad23838fae3108a8de48a1972a9f75 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 1 Jun 2018 15:26:00 -0700 Subject: updated migrations artifacts --- ...tWithTimeLockExceptRemoveAuthorizedAddress.json | 736 ++++++++++++++++++++- 1 file changed, 735 insertions(+), 1 deletion(-) diff --git a/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json b/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json index b3d1eca61..53099f1e4 100644 --- a/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json +++ b/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json @@ -1,4 +1,5 @@ { +<<<<<<< HEAD "schemaVersion": "2.0.0", "contractName": "MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress", "compilerOutput": { @@ -720,4 +721,737 @@ } }, "networks": {} -} \ No newline at end of file +} +======= + "schemaVersion": "2.0.0", + "contractName": "MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress", + "compilerOutput": { + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "owners", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "removeOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "name": "revokeConfirmation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "isOwner", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "confirmations", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "secondsTimeLocked", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "pending", + "type": "bool" + }, + { + "name": "executed", + "type": "bool" + } + ], + "name": "getTransactionCount", + "outputs": [ + { + "name": "count", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "data", + "type": "bytes" + } + ], + "name": "isFunctionRemoveAuthorizedAddress", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "name": "executeRemoveAuthorizedAddress", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "addOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "name": "isConfirmed", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_secondsTimeLocked", + "type": "uint256" + } + ], + "name": "changeTimeLock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "name": "getConfirmationCount", + "outputs": [ + { + "name": "count", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "transactions", + "outputs": [ + { + "name": "destination", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "executed", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwners", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "from", + "type": "uint256" + }, + { + "name": "to", + "type": "uint256" + }, + { + "name": "pending", + "type": "bool" + }, + { + "name": "executed", + "type": "bool" + } + ], + "name": "getTransactionIds", + "outputs": [ + { + "name": "_transactionIds", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "TOKEN_TRANSFER_PROXY_CONTRACT", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "name": "getConfirmations", + "outputs": [ + { + "name": "_confirmations", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "transactionCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_required", + "type": "uint256" + } + ], + "name": "changeRequirement", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "name": "confirmTransaction", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "destination", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + } + ], + "name": "submitTransaction", + "outputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "confirmationTimes", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_OWNER_COUNT", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "required", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "newOwner", + "type": "address" + } + ], + "name": "replaceOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "transactionId", + "type": "uint256" + } + ], + "name": "executeTransaction", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_owners", + "type": "address[]" + }, + { + "name": "_required", + "type": "uint256" + }, + { + "name": "_secondsTimeLocked", + "type": "uint256" + }, + { + "name": "_tokenTransferProxy", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "transactionId", + "type": "uint256" + }, + { + "indexed": false, + "name": "confirmationTime", + "type": "uint256" + } + ], + "name": "ConfirmationTimeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "secondsTimeLocked", + "type": "uint256" + } + ], + "name": "TimeLockChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "name": "transactionId", + "type": "uint256" + } + ], + "name": "Confirmation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "name": "transactionId", + "type": "uint256" + } + ], + "name": "Revocation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "transactionId", + "type": "uint256" + } + ], + "name": "Submission", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "transactionId", + "type": "uint256" + } + ], + "name": "Execution", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "transactionId", + "type": "uint256" + } + ], + "name": "ExecutionFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + } + ], + "name": "OwnerAddition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + } + ], + "name": "OwnerRemoval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "required", + "type": "uint256" + } + ], + "name": "RequirementChange", + "type": "event" + } + ], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": + "0x60806040523480156200001157600080fd5b5060405162001b2738038062001b278339810160409081528151602083015191830151606084015191909301805190939190849084908490839083906000908260328211806200006057508181115b806200006a575080155b8062000074575081155b156200007f57600080fd5b600092505b84518310156200015357600260008685815181101515620000a157fe5b6020908102909101810151600160a060020a031682528101919091526040016000205460ff1680620000f457508483815181101515620000dd57fe5b90602001906020020151600160a060020a03166000145b15620000ff57600080fd5b60016002600087868151811015156200011457fe5b602090810291909101810151600160a060020a03168252810191909152604001600020805460ff19169115159190911790556001929092019162000084565b845162000168906003906020880190620001a2565b5050506004919091555050600655505060088054600160a060020a031916600160a060020a03929092169190911790555062000236915050565b828054828255906000526020600020908101928215620001fa579160200282015b82811115620001fa5782518254600160a060020a031916600160a060020a03909116178255602090920191600190910190620001c3565b50620002089291506200020c565b5090565b6200023391905b8082111562000208578054600160a060020a031916815560010162000213565b90565b6118e180620002466000396000f3006080604052600436106101455763ffffffff60e060020a600035041663025e7c278114610187578063173825d9146101bb57806320ea8d86146101dc5780632f54bf6e146101f45780633411c81c1461022957806337bd78a01461024d5780635474152514610274578063553a48fd146102935780635711b311146102ec5780637065cb4814610304578063784547a7146103255780637ad28c511461033d5780638b51d13f146103555780639ace38c21461036d578063a0e67e2b14610428578063a8abe69a1461048d578063add1cbc5146104b2578063b5dc40c3146104c7578063b77bf600146104df578063ba51a6df146104f4578063c01a8c841461050c578063c642747414610524578063d38f2d821461058d578063d74f8edd146105a5578063dc8452cd146105ba578063e20056e6146105cf578063ee22610b146105f6575b60003411156101855760408051348152905133917fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c919081900360200190a25b005b34801561019357600080fd5b5061019f60043561060e565b60408051600160a060020a039092168252519081900360200190f35b3480156101c757600080fd5b50610185600160a060020a0360043516610636565b3480156101e857600080fd5b5061018560043561079b565b34801561020057600080fd5b50610215600160a060020a036004351661086a565b604080519115158252519081900360200190f35b34801561023557600080fd5b50610215600435600160a060020a036024351661087f565b34801561025957600080fd5b5061026261089f565b60408051918252519081900360200190f35b34801561028057600080fd5b50610262600435151560243515156108a5565b34801561029f57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102159436949293602493928401919081908401838280828437509497506109119650505050505050565b3480156102f857600080fd5b506101856004356109b4565b34801561031057600080fd5b50610185600160a060020a0360043516610bc7565b34801561033157600080fd5b50610215600435610cc5565b34801561034957600080fd5b50610185600435610d42565b34801561036157600080fd5b50610262600435610d89565b34801561037957600080fd5b50610385600435610df8565b6040518085600160a060020a0316600160a060020a031681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156103ea5781810151838201526020016103d2565b50505050905090810190601f1680156104175780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561043457600080fd5b5061043d610eb6565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610479578181015183820152602001610461565b505050509050019250505060405180910390f35b34801561049957600080fd5b5061043d60043560243560443515156064351515610f19565b3480156104be57600080fd5b5061019f611052565b3480156104d357600080fd5b5061043d600435611061565b3480156104eb57600080fd5b506102626111da565b34801561050057600080fd5b506101856004356111e0565b34801561051857600080fd5b50610185600435611257565b34801561053057600080fd5b50604080516020600460443581810135601f8101849004840285018401909552848452610262948235600160a060020a031694602480359536959460649492019190819084018382808284375094975061133e9650505050505050565b34801561059957600080fd5b5061026260043561135d565b3480156105b157600080fd5b5061026261136f565b3480156105c657600080fd5b50610262611374565b3480156105db57600080fd5b50610185600160a060020a036004358116906024351661137a565b34801561060257600080fd5b506101856004356114e0565b600380548290811061061c57fe5b600091825260209091200154600160a060020a0316905081565b600033301461064457600080fd5b600160a060020a038216600090815260026020526040902054829060ff16151561066d57600080fd5b600160a060020a0383166000908152600260205260408120805460ff1916905591505b600354600019018210156107485782600160a060020a03166003838154811015156106b757fe5b600091825260209091200154600160a060020a0316141561073d576003805460001981019081106106e457fe5b60009182526020909120015460038054600160a060020a03909216918490811061070a57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a03160217905550610748565b600190910190610690565b60038054600019019061075b9082611774565b50600354600454111561077457600354610774906111e0565b604051600160a060020a0384169060008051602061189683398151915290600090a2505050565b3360008181526002602052604090205460ff1615156107b957600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1615156107e557600080fd5b600084815260208190526040902060030154849060ff161561080657600080fd5b8461081081610cc5565b1561081a57600080fd5b6000868152600160209081526040808320338085529252808320805460ff191690555188927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a3505050505050565b60026020526000908152604090205460ff1681565b600160209081526000928352604080842090915290825290205460ff1681565b60065481565b6000805b60055481101561090a578380156108d2575060008181526020819052604090206003015460ff16155b806108f657508280156108f6575060008181526020819052604090206003015460ff165b15610902576001820191505b6001016108a9565b5092915050565b604080517f72656d6f7665417574686f72697a65644164647265737328616464726573732981529051908190036020019020600090815b60048110156109a85781816004811061095d57fe5b1a60f860020a02600160f860020a031916848281518110151561097c57fe5b60209101015160f860020a9081900402600160f860020a031916146109a057600080fd5b600101610948565b600192505b5050919050565b600081815260208190526040812060030154829060ff16156109d557600080fd5b826109df81610cc5565b15156109ea57600080fd5b60008481526020819052604090206008548154869291600160a060020a03918216911614610a1757600080fd5b600281810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452610aac939291830182828015610aa25780601f10610a7757610100808354040283529160200191610aa2565b820191906000526020600020905b815481529060010190602001808311610a8557829003601f168201915b5050505050610911565b1515610ab757600080fd5b6000868152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959b50600160a060020a0390931695949293919283928592600019918316156101000291909101909116048015610b605780601f10610b3557610100808354040283529160200191610b60565b820191906000526020600020905b815481529060010190602001808311610b4357829003601f168201915b505091505060006040518083038185875af19250505015610b9957604051869060008051602061187683398151915290600090a2610bbf565b604051869060008051602061183683398151915290600090a260038501805460ff191690555b505050505050565b333014610bd357600080fd5b600160a060020a038116600090815260026020526040902054819060ff1615610bfb57600080fd5b81600160a060020a0381161515610c1157600080fd5b6003805490506001016004546032821180610c2b57508181115b80610c34575080155b80610c3d575081155b15610c4757600080fd5b600160a060020a038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b018054600160a060020a03191684179055516000805160206118568339815191529190a25050505050565b600080805b6003548110156109ad5760008481526001602052604081206003805491929184908110610cf357fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610d27576001820191505b600454821415610d3a57600192506109ad565b600101610cca565b333014610d4e57600080fd5b60068190556040805182815290517fd1c9101a34feff75cccef14a28785a0279cb0b49c1f321f21f5f422e746b43779181900360200190a150565b6000805b600354811015610df25760008381526001602052604081206003805491929184908110610db657fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610dea576001820191505b600101610d8d565b50919050565b6000602081815291815260409081902080546001808301546002808501805487516101009582161595909502600019011691909104601f8101889004880284018801909652858352600160a060020a0390931695909491929190830182828015610ea35780601f10610e7857610100808354040283529160200191610ea3565b820191906000526020600020905b815481529060010190602001808311610e8657829003601f168201915b5050506003909301549192505060ff1684565b60606003805480602002602001604051908101604052809291908181526020018280548015610f0e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610ef0575b505050505090505b90565b606080600080600554604051908082528060200260200182016040528015610f4b578160200160208202803883390190505b50925060009150600090505b600554811015610fd257858015610f80575060008181526020819052604090206003015460ff16155b80610fa45750848015610fa4575060008181526020819052604090206003015460ff165b15610fca57808383815181101515610fb857fe5b60209081029091010152600191909101905b600101610f57565b878703604051908082528060200260200182016040528015610ffe578160200160208202803883390190505b5093508790505b8681101561104757828181518110151561101b57fe5b906020019060200201518489830381518110151561103557fe5b60209081029091010152600101611005565b505050949350505050565b600854600160a060020a031681565b606080600080600380549050604051908082528060200260200182016040528015611096578160200160208202803883390190505b50925060009150600090505b60035481101561115357600085815260016020526040812060038054919291849081106110cb57fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff161561114b57600380548290811061110657fe5b6000918252602090912001548351600160a060020a039091169084908490811061112c57fe5b600160a060020a03909216602092830290910190910152600191909101905b6001016110a2565b8160405190808252806020026020018201604052801561117d578160200160208202803883390190505b509350600090505b818110156111d257828181518110151561119b57fe5b9060200190602002015184828151811015156111b357fe5b600160a060020a03909216602092830290910190910152600101611185565b505050919050565b60055481565b3330146111ec57600080fd5b6003548160328211806111fe57508181115b80611207575080155b80611210575081155b1561121a57600080fd5b60048390556040805184815290517fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9181900360200190a1505050565b3360008181526002602052604090205460ff16151561127557600080fd5b6000828152602081905260409020548290600160a060020a0316151561129a57600080fd5b60008381526001602090815260408083203380855292529091205484919060ff16156112c557600080fd5b846112cf81610cc5565b156112d957600080fd5b6000868152600160208181526040808420338086529252808420805460ff1916909317909255905188927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a361132f86610cc5565b15610bbf57610bbf8642611646565b600061134b848484611691565b905061135681611257565b9392505050565b60076020526000908152604090205481565b603281565b60045481565b600033301461138857600080fd5b600160a060020a038316600090815260026020526040902054839060ff1615156113b157600080fd5b600160a060020a038316600090815260026020526040902054839060ff16156113d957600080fd5b600092505b60035483101561146a5784600160a060020a031660038481548110151561140157fe5b600091825260209091200154600160a060020a0316141561145f578360038481548110151561142c57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a0316021790555061146a565b6001909201916113de565b600160a060020a03808616600081815260026020526040808220805460ff19908116909155938816825280822080549094166001179093559151909160008051602061189683398151915291a2604051600160a060020a0385169060008051602061185683398151915290600090a25050505050565b600081815260208190526040812060030154829060ff161561150157600080fd5b8261150b81610cc5565b151561151657600080fd5b60065460008581526007602052604090205485910142101561153757600080fd5b6000858152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959a50600160a060020a03909316959492939192839285926000199183161561010002919091019091160480156115e05780601f106115b5576101008083540402835291602001916115e0565b820191906000526020600020905b8154815290600101906020018083116115c357829003601f168201915b505091505060006040518083038185875af1925050501561161957604051859060008051602061187683398151915290600090a261163f565b604051859060008051602061183683398151915290600090a260038401805460ff191690555b5050505050565b6000828152600760209081526040918290208390558151838152915184927f0b237afe65f1514fd7ea3f923ea4fe792bdd07000a912b6cd1602a8e7f573c8d92908290030190a25050565b600083600160a060020a03811615156116a957600080fd5b60055460408051608081018252600160a060020a03888116825260208083018981528385018981526000606086018190528781528084529590952084518154600160a060020a0319169416939093178355516001830155925180519496509193909261171c92600285019291019061179d565b50606091909101516003909101805460ff191691151591909117905560058054600101905560405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b8154818355818111156117985760008381526020902061179891810190830161181b565b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106117de57805160ff191683800117855561180b565b8280016001018555821561180b579182015b8281111561180b5782518255916020019190600101906117f0565b5061181792915061181b565b5090565b610f1691905b8082111561181757600081556001016118215600526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b79236f39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed758001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b90a165627a7a723058200853bb251860c92945a3c94ebbaa86cbe3f8b7ed5e95b484f428752638c133800029", + "opcodes": + "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1B27 CODESIZE SUB DUP1 PUSH3 0x1B27 DUP4 CODECOPY DUP2 ADD PUSH1 0x40 SWAP1 DUP2 MSTORE DUP2 MLOAD PUSH1 0x20 DUP4 ADD MLOAD SWAP2 DUP4 ADD MLOAD PUSH1 0x60 DUP5 ADD MLOAD SWAP2 SWAP1 SWAP4 ADD DUP1 MLOAD SWAP1 SWAP4 SWAP2 SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP4 SWAP1 DUP4 SWAP1 PUSH1 0x0 SWAP1 DUP3 PUSH1 0x32 DUP3 GT DUP1 PUSH3 0x60 JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH3 0x6A JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH3 0x74 JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH3 0x7F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 SWAP3 POP JUMPDEST DUP5 MLOAD DUP4 LT ISZERO PUSH3 0x153 JUMPI PUSH1 0x2 PUSH1 0x0 DUP7 DUP6 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0xA1 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD DUP2 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP3 MSTORE DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH1 0xFF AND DUP1 PUSH3 0xF4 JUMPI POP DUP5 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0xDD JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x0 EQ JUMPDEST ISZERO PUSH3 0xFF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0x2 PUSH1 0x0 DUP8 DUP7 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x114 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP2 SWAP1 SWAP2 ADD DUP2 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP3 MSTORE DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 ADD PUSH1 0x0 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP2 ISZERO ISZERO SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH1 0x1 SWAP3 SWAP1 SWAP3 ADD SWAP2 PUSH3 0x84 JUMP JUMPDEST DUP5 MLOAD PUSH3 0x168 SWAP1 PUSH1 0x3 SWAP1 PUSH1 0x20 DUP9 ADD SWAP1 PUSH3 0x1A2 JUMP JUMPDEST POP POP POP PUSH1 0x4 SWAP2 SWAP1 SWAP2 SSTORE POP POP PUSH1 0x6 SSTORE POP POP PUSH1 0x8 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP3 SWAP1 SWAP3 AND SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE POP PUSH3 0x236 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD DUP3 DUP3 SSTORE SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 DUP2 ADD SWAP3 DUP3 ISZERO PUSH3 0x1FA JUMPI SWAP2 PUSH1 0x20 MUL DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x1FA JUMPI DUP3 MLOAD DUP3 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP2 AND OR DUP3 SSTORE PUSH1 0x20 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH3 0x1C3 JUMP JUMPDEST POP PUSH3 0x208 SWAP3 SWAP2 POP PUSH3 0x20C JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x233 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x208 JUMPI DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND DUP2 SSTORE PUSH1 0x1 ADD PUSH3 0x213 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x18E1 DUP1 PUSH3 0x246 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x145 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x25E7C27 DUP2 EQ PUSH2 0x187 JUMPI DUP1 PUSH4 0x173825D9 EQ PUSH2 0x1BB JUMPI DUP1 PUSH4 0x20EA8D86 EQ PUSH2 0x1DC JUMPI DUP1 PUSH4 0x2F54BF6E EQ PUSH2 0x1F4 JUMPI DUP1 PUSH4 0x3411C81C EQ PUSH2 0x229 JUMPI DUP1 PUSH4 0x37BD78A0 EQ PUSH2 0x24D JUMPI DUP1 PUSH4 0x54741525 EQ PUSH2 0x274 JUMPI DUP1 PUSH4 0x553A48FD EQ PUSH2 0x293 JUMPI DUP1 PUSH4 0x5711B311 EQ PUSH2 0x2EC JUMPI DUP1 PUSH4 0x7065CB48 EQ PUSH2 0x304 JUMPI DUP1 PUSH4 0x784547A7 EQ PUSH2 0x325 JUMPI DUP1 PUSH4 0x7AD28C51 EQ PUSH2 0x33D JUMPI DUP1 PUSH4 0x8B51D13F EQ PUSH2 0x355 JUMPI DUP1 PUSH4 0x9ACE38C2 EQ PUSH2 0x36D JUMPI DUP1 PUSH4 0xA0E67E2B EQ PUSH2 0x428 JUMPI DUP1 PUSH4 0xA8ABE69A EQ PUSH2 0x48D JUMPI DUP1 PUSH4 0xADD1CBC5 EQ PUSH2 0x4B2 JUMPI DUP1 PUSH4 0xB5DC40C3 EQ PUSH2 0x4C7 JUMPI DUP1 PUSH4 0xB77BF600 EQ PUSH2 0x4DF JUMPI DUP1 PUSH4 0xBA51A6DF EQ PUSH2 0x4F4 JUMPI DUP1 PUSH4 0xC01A8C84 EQ PUSH2 0x50C JUMPI DUP1 PUSH4 0xC6427474 EQ PUSH2 0x524 JUMPI DUP1 PUSH4 0xD38F2D82 EQ PUSH2 0x58D JUMPI DUP1 PUSH4 0xD74F8EDD EQ PUSH2 0x5A5 JUMPI DUP1 PUSH4 0xDC8452CD EQ PUSH2 0x5BA JUMPI DUP1 PUSH4 0xE20056E6 EQ PUSH2 0x5CF JUMPI DUP1 PUSH4 0xEE22610B EQ PUSH2 0x5F6 JUMPI JUMPDEST PUSH1 0x0 CALLVALUE GT ISZERO PUSH2 0x185 JUMPI PUSH1 0x40 DUP1 MLOAD CALLVALUE DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0xE1FFFCC4923D04B559F4D29A8BFC6CDA04EB5B0D3C460751C2402C5C5CC9109C SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x193 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH1 0x4 CALLDATALOAD PUSH2 0x60E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x636 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1E8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x79B JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x200 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x86A JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x235 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x24 CALLDATALOAD AND PUSH2 0x87F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x259 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x89F JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x280 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD ISZERO ISZERO PUSH1 0x24 CALLDATALOAD ISZERO ISZERO PUSH2 0x8A5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x29F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 DUP1 CALLDATALOAD DUP1 DUP3 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x215 SWAP5 CALLDATASIZE SWAP5 SWAP3 SWAP4 PUSH1 0x24 SWAP4 SWAP3 DUP5 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x911 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x9B4 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x310 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0xBC7 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x331 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH2 0xCC5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x349 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0xD42 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x361 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0xD89 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x379 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x385 PUSH1 0x4 CALLDATALOAD PUSH2 0xDF8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP6 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x20 ADD DUP5 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x3EA JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x3D2 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x417 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP6 POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x434 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH2 0xEB6 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 DUP2 ADD SWAP2 MUL DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x479 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x461 JUMP JUMPDEST POP POP POP POP SWAP1 POP ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x499 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH1 0x24 CALLDATALOAD PUSH1 0x44 CALLDATALOAD ISZERO ISZERO PUSH1 0x64 CALLDATALOAD ISZERO ISZERO PUSH2 0xF19 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4BE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH2 0x1052 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4D3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH2 0x1061 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4EB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x11DA JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x500 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x11E0 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x518 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x1257 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x530 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 PUSH1 0x44 CALLDATALOAD DUP2 DUP2 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x262 SWAP5 DUP3 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP5 PUSH1 0x24 DUP1 CALLDATALOAD SWAP6 CALLDATASIZE SWAP6 SWAP5 PUSH1 0x64 SWAP5 SWAP3 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x133E SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x599 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0x135D JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x136F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5C6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x1374 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH2 0x137A JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x602 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x14E0 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x61C JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 POP DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x644 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x66D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE SWAP2 POP JUMPDEST PUSH1 0x3 SLOAD PUSH1 0x0 NOT ADD DUP3 LT ISZERO PUSH2 0x748 JUMPI DUP3 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x6B7 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x73D JUMPI PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT DUP2 ADD SWAP1 DUP2 LT PUSH2 0x6E4 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x70A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x748 JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH2 0x690 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT ADD SWAP1 PUSH2 0x75B SWAP1 DUP3 PUSH2 0x1774 JUMP JUMPDEST POP PUSH1 0x3 SLOAD PUSH1 0x4 SLOAD GT ISZERO PUSH2 0x774 JUMPI PUSH1 0x3 SLOAD PUSH2 0x774 SWAP1 PUSH2 0x11E0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP5 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7B9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP4 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7E5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD DUP5 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x806 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x810 DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x81A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE DUP1 DUP4 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE MLOAD DUP9 SWAP3 PUSH32 0xF6A317157440607F36269043EB55F1287A5A19BA2216AFEAB88CD46CBCFB88E9 SWAP2 LOG3 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x0 SWAP3 DUP4 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 SWAP1 SWAP2 MSTORE SWAP1 DUP3 MSTORE SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0x90A JUMPI DUP4 DUP1 ISZERO PUSH2 0x8D2 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0x8F6 JUMPI POP DUP3 DUP1 ISZERO PUSH2 0x8F6 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0x902 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0x8A9 JUMP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x72656D6F7665417574686F72697A656441646472657373286164647265737329 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 KECCAK256 PUSH1 0x0 SWAP1 DUP2 JUMPDEST PUSH1 0x4 DUP2 LT ISZERO PUSH2 0x9A8 JUMPI DUP2 DUP2 PUSH1 0x4 DUP2 LT PUSH2 0x95D JUMPI INVALID JUMPDEST BYTE PUSH1 0xF8 PUSH1 0x2 EXP MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x97C JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP2 ADD ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND EQ PUSH2 0x9A0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 ADD PUSH2 0x948 JUMP JUMPDEST PUSH1 0x1 SWAP3 POP JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x9D5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x9DF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x9EA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x8 SLOAD DUP2 SLOAD DUP7 SWAP3 SWAP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP2 DUP3 AND SWAP2 AND EQ PUSH2 0xA17 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x2 DUP2 DUP2 ADD DUP1 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x1 DUP5 AND ISZERO PUSH2 0x100 MUL PUSH1 0x0 NOT ADD SWAP1 SWAP4 AND SWAP5 SWAP1 SWAP5 DIV PUSH1 0x1F DUP2 ADD DUP4 SWAP1 DIV DUP4 MUL DUP6 ADD DUP4 ADD SWAP1 SWAP2 MSTORE DUP1 DUP5 MSTORE PUSH2 0xAAC SWAP4 SWAP3 SWAP2 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xAA2 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA77 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAA2 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA85 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP PUSH2 0x911 JUMP JUMPDEST ISZERO ISZERO PUSH2 0xAB7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP12 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0xB60 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB35 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB60 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB43 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0xB99 JUMPI PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0xBBF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP6 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP POP JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xBD3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0xBFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0xC11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x1 ADD PUSH1 0x4 SLOAD PUSH1 0x32 DUP3 GT DUP1 PUSH2 0xC2B JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0xC34 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0xC3D JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0xC47 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE PUSH1 0x3 DUP1 SLOAD SWAP2 DUP3 ADD DUP2 SSTORE DUP4 MSTORE PUSH32 0xC2575A0E9E593C00F959F8C92F12DB2869C3395A3B0502D05E2516446F71F85B ADD DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND DUP5 OR SWAP1 SSTORE MLOAD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x9AD JUMPI PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xCF3 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xD27 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x4 SLOAD DUP3 EQ ISZERO PUSH2 0xD3A JUMPI PUSH1 0x1 SWAP3 POP PUSH2 0x9AD JUMP JUMPDEST PUSH1 0x1 ADD PUSH2 0xCCA JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xD4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 DUP2 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP3 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xD1C9101A34FEFF75CCCEF14A28785A0279CB0B49C1F321F21F5F422E746B4377 SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0xDF2 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xDB6 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xDEA JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0xD8D JUMP JUMPDEST POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP2 DUP2 MSTORE SWAP2 DUP2 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 DUP1 SLOAD PUSH1 0x1 DUP1 DUP4 ADD SLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD DUP8 MLOAD PUSH2 0x100 SWAP6 DUP3 AND ISZERO SWAP6 SWAP1 SWAP6 MUL PUSH1 0x0 NOT ADD AND SWAP2 SWAP1 SWAP2 DIV PUSH1 0x1F DUP2 ADD DUP9 SWAP1 DIV DUP9 MUL DUP5 ADD DUP9 ADD SWAP1 SWAP7 MSTORE DUP6 DUP4 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP1 SWAP5 SWAP2 SWAP3 SWAP2 SWAP1 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xEA3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xE78 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xEA3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xE86 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP PUSH1 0x3 SWAP1 SWAP4 ADD SLOAD SWAP2 SWAP3 POP POP PUSH1 0xFF AND DUP5 JUMP JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD DUP1 ISZERO PUSH2 0xF0E JUMPI PUSH1 0x20 MUL DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xEF0 JUMPI JUMPDEST POP POP POP POP POP SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x5 SLOAD PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xF4B JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0xFD2 JUMPI DUP6 DUP1 ISZERO PUSH2 0xF80 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0xFA4 JUMPI POP DUP5 DUP1 ISZERO PUSH2 0xFA4 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0xFCA JUMPI DUP1 DUP4 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xFB8 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0xF57 JUMP JUMPDEST DUP8 DUP8 SUB PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xFFE JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP DUP8 SWAP1 POP JUMPDEST DUP7 DUP2 LT ISZERO PUSH2 0x1047 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP10 DUP4 SUB DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1035 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1005 JUMP JUMPDEST POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x8 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x1096 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x1153 JUMPI PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x10CB JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0x114B JUMPI PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x1106 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP2 AND SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP2 LT PUSH2 0x112C JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0x10A2 JUMP JUMPDEST DUP2 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x117D JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP2 DUP2 LT ISZERO PUSH2 0x11D2 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x119B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x11B3 JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1185 JUMP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x5 SLOAD DUP2 JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0x11EC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 SLOAD DUP2 PUSH1 0x32 DUP3 GT DUP1 PUSH2 0x11FE JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0x1207 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0x1210 JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0x121A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x4 DUP4 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xA3F1EE9126A074D9326C682F561767F710E927FAA811F7A99829D49DC421797A SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x1275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND ISZERO ISZERO PUSH2 0x129A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP5 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x12C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x12CF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x12D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 DUP2 DUP2 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 CALLER DUP1 DUP7 MSTORE SWAP3 MSTORE DUP1 DUP5 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SWAP4 OR SWAP1 SWAP3 SSTORE SWAP1 MLOAD DUP9 SWAP3 PUSH32 0x4A504A94899432A9846E1AA406DCEB1BCFD538BB839071D49D1E5E23F5BE30EF SWAP2 LOG3 PUSH2 0x132F DUP7 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0xBBF JUMPI PUSH2 0xBBF DUP7 TIMESTAMP PUSH2 0x1646 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x134B DUP5 DUP5 DUP5 PUSH2 0x1691 JUMP JUMPDEST SWAP1 POP PUSH2 0x1356 DUP2 PUSH2 0x1257 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x32 DUP2 JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x1388 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x13B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x13D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 SWAP3 POP JUMPDEST PUSH1 0x3 SLOAD DUP4 LT ISZERO PUSH2 0x146A JUMPI DUP5 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1401 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x145F JUMPI DUP4 PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x142C JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x146A JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP3 ADD SWAP2 PUSH2 0x13DE JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP1 DUP7 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT SWAP1 DUP2 AND SWAP1 SWAP2 SSTORE SWAP4 DUP9 AND DUP3 MSTORE DUP1 DUP3 KECCAK256 DUP1 SLOAD SWAP1 SWAP5 AND PUSH1 0x1 OR SWAP1 SWAP4 SSTORE SWAP2 MLOAD SWAP1 SWAP2 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 LOG2 PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x1501 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x150B DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x1516 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 SLOAD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP6 SWAP2 ADD TIMESTAMP LT ISZERO PUSH2 0x1537 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP11 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0x15E0 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x15B5 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x15E0 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x15C3 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0x1619 JUMPI PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0x163F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP5 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP2 DUP3 SWAP1 KECCAK256 DUP4 SWAP1 SSTORE DUP2 MLOAD DUP4 DUP2 MSTORE SWAP2 MLOAD DUP5 SWAP3 PUSH32 0xB237AFE65F1514FD7EA3F923EA4FE792BDD07000A912B6CD1602A8E7F573C8D SWAP3 SWAP1 DUP3 SWAP1 SUB ADD SWAP1 LOG2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0x16A9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x5 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP9 DUP2 AND DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 ADD DUP10 DUP2 MSTORE DUP4 DUP6 ADD DUP10 DUP2 MSTORE PUSH1 0x0 PUSH1 0x60 DUP7 ADD DUP2 SWAP1 MSTORE DUP8 DUP2 MSTORE DUP1 DUP5 MSTORE SWAP6 SWAP1 SWAP6 KECCAK256 DUP5 MLOAD DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND SWAP5 AND SWAP4 SWAP1 SWAP4 OR DUP4 SSTORE MLOAD PUSH1 0x1 DUP4 ADD SSTORE SWAP3 MLOAD DUP1 MLOAD SWAP5 SWAP7 POP SWAP2 SWAP4 SWAP1 SWAP3 PUSH2 0x171C SWAP3 PUSH1 0x2 DUP6 ADD SWAP3 SWAP2 ADD SWAP1 PUSH2 0x179D JUMP JUMPDEST POP PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD MLOAD PUSH1 0x3 SWAP1 SWAP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP2 ISZERO ISZERO SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE PUSH1 0x40 MLOAD DUP3 SWAP1 PUSH32 0xC0BA8FE4B176C1714197D43B9CC6BCF797A4A7461C5FE8D0EF6E184AE7601E51 SWAP1 PUSH1 0x0 SWAP1 LOG2 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 GT ISZERO PUSH2 0x1798 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x20 SWAP1 KECCAK256 PUSH2 0x1798 SWAP2 DUP2 ADD SWAP1 DUP4 ADD PUSH2 0x181B JUMP JUMPDEST POP POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x17DE JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x180B JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x180B JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x180B JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x17F0 JUMP JUMPDEST POP PUSH2 0x1817 SWAP3 SWAP2 POP PUSH2 0x181B JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH2 0xF16 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1817 JUMPI PUSH1 0x0 DUP2 SSTORE PUSH1 0x1 ADD PUSH2 0x1821 JUMP STOP MSTORE PUSH5 0x41BB6C1ABA EXTCODECOPY SWAP11 0x4a PUSH13 0xA1D6545DA9C2333C8C48343EF3 SWAP9 0xeb DUP6 DUP14 PUSH19 0xB79236F39E6E1EB0EDCF53C221607B54B00CD2 DUP16 BALANCE SWAP7 INVALID 0xd0 LOG2 0x49 SWAP5 0xdc ADDRESS DUP12 DUP16 PUSH2 0x1B68 0x2d CALLER 0xe1 RETURNDATACOPY 0xcb SLOAD 0xc3 SMOD PUSH14 0x8E8BB8C2881800A4D972B792045F STATICCALL 0xe9 DUP16 0xdf 0x46 0xdf CALLDATASIZE 0x5f 0xed PUSH22 0x8001553A916EF2F495D26A907CC54D96ED840D7BDA71 0xe7 BALANCE SWAP5 0xbf GAS SWAP14 0xf7 0xa7 PUSH12 0x90A165627A7A723058200853 0xbb 0x25 XOR PUSH1 0xC9 0x29 GASLIMIT LOG3 0xc9 0x4e 0xbb 0xaa DUP7 0xcb 0xe3 0xf8 0xb7 0xed 0x5e SWAP6 0xb4 DUP5 DELEGATECALL 0x28 PUSH22 0x2638C133800029000000000000000000000000000000 ", + "sourceMap": + "714:2422:2:-;;;1582:349;8:9:-1;5:2;;;30:1;27;20:12;5:2;1582:349:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2913:14:0;;1582:349:2;;;;;;;;;;;;;;2959:6:0;;1582:349:2;256:2:0;2236:28;;;:66;;;2292:10;2280:9;:22;2236:66;:96;;;-1:-1:-1;2318:14:0;;2236:96;:127;;;-1:-1:-1;2348:15:0;;2236:127;2229:153;;;2377:5;;;2229:153;2966:1;2959:8;;2954:168;2971:7;:14;2969:1;:16;2954:168;;;3010:7;:19;3018:7;3026:1;3018:10;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3010:19:0;;;;;;;;;;;-1:-1:-1;3010:19:0;;;;;:38;;;3033:7;3041:1;3033:10;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3033:15:0;3047:1;3033:15;3010:38;3006:65;;;3066:5;;;3006:65;3107:4;3085:7;:19;3093:7;3101:1;3093:10;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3085:19:0;;;;;;;;;;;-1:-1:-1;3085:19:0;:26;;-1:-1:-1;;3085:26:0;;;;;;;;;;-1:-1:-1;2987:3:0;;;;;2954:168;;;3131:16;;;;:6;;:16;;;;;:::i;:::-;-1:-1:-1;;;3157:8:0;:20;;;;-1:-1:-1;;2072:17:1;:38;-1:-1:-1;;1873:29:2;:51;;-1:-1:-1;;;;;;1873:51:2;-1:-1:-1;;;;;1873:51:2;;;;;;;;;;-1:-1:-1;714:2422:2;;-1:-1:-1;;714:2422:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;714:2422:2;-1:-1:-1;;;;;714:2422:2;;;;;;;;;;;-1:-1:-1;714:2422:2;;;;;;;-1:-1:-1;714:2422:2;;;-1:-1:-1;714:2422:2;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;;714:2422:2;;;;;;;;;:::o;:::-;;;;;;;" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": + "0x6080604052600436106101455763ffffffff60e060020a600035041663025e7c278114610187578063173825d9146101bb57806320ea8d86146101dc5780632f54bf6e146101f45780633411c81c1461022957806337bd78a01461024d5780635474152514610274578063553a48fd146102935780635711b311146102ec5780637065cb4814610304578063784547a7146103255780637ad28c511461033d5780638b51d13f146103555780639ace38c21461036d578063a0e67e2b14610428578063a8abe69a1461048d578063add1cbc5146104b2578063b5dc40c3146104c7578063b77bf600146104df578063ba51a6df146104f4578063c01a8c841461050c578063c642747414610524578063d38f2d821461058d578063d74f8edd146105a5578063dc8452cd146105ba578063e20056e6146105cf578063ee22610b146105f6575b60003411156101855760408051348152905133917fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c919081900360200190a25b005b34801561019357600080fd5b5061019f60043561060e565b60408051600160a060020a039092168252519081900360200190f35b3480156101c757600080fd5b50610185600160a060020a0360043516610636565b3480156101e857600080fd5b5061018560043561079b565b34801561020057600080fd5b50610215600160a060020a036004351661086a565b604080519115158252519081900360200190f35b34801561023557600080fd5b50610215600435600160a060020a036024351661087f565b34801561025957600080fd5b5061026261089f565b60408051918252519081900360200190f35b34801561028057600080fd5b50610262600435151560243515156108a5565b34801561029f57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102159436949293602493928401919081908401838280828437509497506109119650505050505050565b3480156102f857600080fd5b506101856004356109b4565b34801561031057600080fd5b50610185600160a060020a0360043516610bc7565b34801561033157600080fd5b50610215600435610cc5565b34801561034957600080fd5b50610185600435610d42565b34801561036157600080fd5b50610262600435610d89565b34801561037957600080fd5b50610385600435610df8565b6040518085600160a060020a0316600160a060020a031681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156103ea5781810151838201526020016103d2565b50505050905090810190601f1680156104175780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561043457600080fd5b5061043d610eb6565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610479578181015183820152602001610461565b505050509050019250505060405180910390f35b34801561049957600080fd5b5061043d60043560243560443515156064351515610f19565b3480156104be57600080fd5b5061019f611052565b3480156104d357600080fd5b5061043d600435611061565b3480156104eb57600080fd5b506102626111da565b34801561050057600080fd5b506101856004356111e0565b34801561051857600080fd5b50610185600435611257565b34801561053057600080fd5b50604080516020600460443581810135601f8101849004840285018401909552848452610262948235600160a060020a031694602480359536959460649492019190819084018382808284375094975061133e9650505050505050565b34801561059957600080fd5b5061026260043561135d565b3480156105b157600080fd5b5061026261136f565b3480156105c657600080fd5b50610262611374565b3480156105db57600080fd5b50610185600160a060020a036004358116906024351661137a565b34801561060257600080fd5b506101856004356114e0565b600380548290811061061c57fe5b600091825260209091200154600160a060020a0316905081565b600033301461064457600080fd5b600160a060020a038216600090815260026020526040902054829060ff16151561066d57600080fd5b600160a060020a0383166000908152600260205260408120805460ff1916905591505b600354600019018210156107485782600160a060020a03166003838154811015156106b757fe5b600091825260209091200154600160a060020a0316141561073d576003805460001981019081106106e457fe5b60009182526020909120015460038054600160a060020a03909216918490811061070a57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a03160217905550610748565b600190910190610690565b60038054600019019061075b9082611774565b50600354600454111561077457600354610774906111e0565b604051600160a060020a0384169060008051602061189683398151915290600090a2505050565b3360008181526002602052604090205460ff1615156107b957600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1615156107e557600080fd5b600084815260208190526040902060030154849060ff161561080657600080fd5b8461081081610cc5565b1561081a57600080fd5b6000868152600160209081526040808320338085529252808320805460ff191690555188927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a3505050505050565b60026020526000908152604090205460ff1681565b600160209081526000928352604080842090915290825290205460ff1681565b60065481565b6000805b60055481101561090a578380156108d2575060008181526020819052604090206003015460ff16155b806108f657508280156108f6575060008181526020819052604090206003015460ff165b15610902576001820191505b6001016108a9565b5092915050565b604080517f72656d6f7665417574686f72697a65644164647265737328616464726573732981529051908190036020019020600090815b60048110156109a85781816004811061095d57fe5b1a60f860020a02600160f860020a031916848281518110151561097c57fe5b60209101015160f860020a9081900402600160f860020a031916146109a057600080fd5b600101610948565b600192505b5050919050565b600081815260208190526040812060030154829060ff16156109d557600080fd5b826109df81610cc5565b15156109ea57600080fd5b60008481526020819052604090206008548154869291600160a060020a03918216911614610a1757600080fd5b600281810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452610aac939291830182828015610aa25780601f10610a7757610100808354040283529160200191610aa2565b820191906000526020600020905b815481529060010190602001808311610a8557829003601f168201915b5050505050610911565b1515610ab757600080fd5b6000868152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959b50600160a060020a0390931695949293919283928592600019918316156101000291909101909116048015610b605780601f10610b3557610100808354040283529160200191610b60565b820191906000526020600020905b815481529060010190602001808311610b4357829003601f168201915b505091505060006040518083038185875af19250505015610b9957604051869060008051602061187683398151915290600090a2610bbf565b604051869060008051602061183683398151915290600090a260038501805460ff191690555b505050505050565b333014610bd357600080fd5b600160a060020a038116600090815260026020526040902054819060ff1615610bfb57600080fd5b81600160a060020a0381161515610c1157600080fd5b6003805490506001016004546032821180610c2b57508181115b80610c34575080155b80610c3d575081155b15610c4757600080fd5b600160a060020a038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b018054600160a060020a03191684179055516000805160206118568339815191529190a25050505050565b600080805b6003548110156109ad5760008481526001602052604081206003805491929184908110610cf357fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610d27576001820191505b600454821415610d3a57600192506109ad565b600101610cca565b333014610d4e57600080fd5b60068190556040805182815290517fd1c9101a34feff75cccef14a28785a0279cb0b49c1f321f21f5f422e746b43779181900360200190a150565b6000805b600354811015610df25760008381526001602052604081206003805491929184908110610db657fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610dea576001820191505b600101610d8d565b50919050565b6000602081815291815260409081902080546001808301546002808501805487516101009582161595909502600019011691909104601f8101889004880284018801909652858352600160a060020a0390931695909491929190830182828015610ea35780601f10610e7857610100808354040283529160200191610ea3565b820191906000526020600020905b815481529060010190602001808311610e8657829003601f168201915b5050506003909301549192505060ff1684565b60606003805480602002602001604051908101604052809291908181526020018280548015610f0e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610ef0575b505050505090505b90565b606080600080600554604051908082528060200260200182016040528015610f4b578160200160208202803883390190505b50925060009150600090505b600554811015610fd257858015610f80575060008181526020819052604090206003015460ff16155b80610fa45750848015610fa4575060008181526020819052604090206003015460ff165b15610fca57808383815181101515610fb857fe5b60209081029091010152600191909101905b600101610f57565b878703604051908082528060200260200182016040528015610ffe578160200160208202803883390190505b5093508790505b8681101561104757828181518110151561101b57fe5b906020019060200201518489830381518110151561103557fe5b60209081029091010152600101611005565b505050949350505050565b600854600160a060020a031681565b606080600080600380549050604051908082528060200260200182016040528015611096578160200160208202803883390190505b50925060009150600090505b60035481101561115357600085815260016020526040812060038054919291849081106110cb57fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff161561114b57600380548290811061110657fe5b6000918252602090912001548351600160a060020a039091169084908490811061112c57fe5b600160a060020a03909216602092830290910190910152600191909101905b6001016110a2565b8160405190808252806020026020018201604052801561117d578160200160208202803883390190505b509350600090505b818110156111d257828181518110151561119b57fe5b9060200190602002015184828151811015156111b357fe5b600160a060020a03909216602092830290910190910152600101611185565b505050919050565b60055481565b3330146111ec57600080fd5b6003548160328211806111fe57508181115b80611207575080155b80611210575081155b1561121a57600080fd5b60048390556040805184815290517fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9181900360200190a1505050565b3360008181526002602052604090205460ff16151561127557600080fd5b6000828152602081905260409020548290600160a060020a0316151561129a57600080fd5b60008381526001602090815260408083203380855292529091205484919060ff16156112c557600080fd5b846112cf81610cc5565b156112d957600080fd5b6000868152600160208181526040808420338086529252808420805460ff1916909317909255905188927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a361132f86610cc5565b15610bbf57610bbf8642611646565b600061134b848484611691565b905061135681611257565b9392505050565b60076020526000908152604090205481565b603281565b60045481565b600033301461138857600080fd5b600160a060020a038316600090815260026020526040902054839060ff1615156113b157600080fd5b600160a060020a038316600090815260026020526040902054839060ff16156113d957600080fd5b600092505b60035483101561146a5784600160a060020a031660038481548110151561140157fe5b600091825260209091200154600160a060020a0316141561145f578360038481548110151561142c57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a0316021790555061146a565b6001909201916113de565b600160a060020a03808616600081815260026020526040808220805460ff19908116909155938816825280822080549094166001179093559151909160008051602061189683398151915291a2604051600160a060020a0385169060008051602061185683398151915290600090a25050505050565b600081815260208190526040812060030154829060ff161561150157600080fd5b8261150b81610cc5565b151561151657600080fd5b60065460008581526007602052604090205485910142101561153757600080fd5b6000858152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959a50600160a060020a03909316959492939192839285926000199183161561010002919091019091160480156115e05780601f106115b5576101008083540402835291602001916115e0565b820191906000526020600020905b8154815290600101906020018083116115c357829003601f168201915b505091505060006040518083038185875af1925050501561161957604051859060008051602061187683398151915290600090a261163f565b604051859060008051602061183683398151915290600090a260038401805460ff191690555b5050505050565b6000828152600760209081526040918290208390558151838152915184927f0b237afe65f1514fd7ea3f923ea4fe792bdd07000a912b6cd1602a8e7f573c8d92908290030190a25050565b600083600160a060020a03811615156116a957600080fd5b60055460408051608081018252600160a060020a03888116825260208083018981528385018981526000606086018190528781528084529590952084518154600160a060020a0319169416939093178355516001830155925180519496509193909261171c92600285019291019061179d565b50606091909101516003909101805460ff191691151591909117905560058054600101905560405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b8154818355818111156117985760008381526020902061179891810190830161181b565b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106117de57805160ff191683800117855561180b565b8280016001018555821561180b579182015b8281111561180b5782518255916020019190600101906117f0565b5061181792915061181b565b5090565b610f1691905b8082111561181757600081556001016118215600526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b79236f39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed758001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b90a165627a7a723058200853bb251860c92945a3c94ebbaa86cbe3f8b7ed5e95b484f428752638c133800029", + "opcodes": + "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x145 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x25E7C27 DUP2 EQ PUSH2 0x187 JUMPI DUP1 PUSH4 0x173825D9 EQ PUSH2 0x1BB JUMPI DUP1 PUSH4 0x20EA8D86 EQ PUSH2 0x1DC JUMPI DUP1 PUSH4 0x2F54BF6E EQ PUSH2 0x1F4 JUMPI DUP1 PUSH4 0x3411C81C EQ PUSH2 0x229 JUMPI DUP1 PUSH4 0x37BD78A0 EQ PUSH2 0x24D JUMPI DUP1 PUSH4 0x54741525 EQ PUSH2 0x274 JUMPI DUP1 PUSH4 0x553A48FD EQ PUSH2 0x293 JUMPI DUP1 PUSH4 0x5711B311 EQ PUSH2 0x2EC JUMPI DUP1 PUSH4 0x7065CB48 EQ PUSH2 0x304 JUMPI DUP1 PUSH4 0x784547A7 EQ PUSH2 0x325 JUMPI DUP1 PUSH4 0x7AD28C51 EQ PUSH2 0x33D JUMPI DUP1 PUSH4 0x8B51D13F EQ PUSH2 0x355 JUMPI DUP1 PUSH4 0x9ACE38C2 EQ PUSH2 0x36D JUMPI DUP1 PUSH4 0xA0E67E2B EQ PUSH2 0x428 JUMPI DUP1 PUSH4 0xA8ABE69A EQ PUSH2 0x48D JUMPI DUP1 PUSH4 0xADD1CBC5 EQ PUSH2 0x4B2 JUMPI DUP1 PUSH4 0xB5DC40C3 EQ PUSH2 0x4C7 JUMPI DUP1 PUSH4 0xB77BF600 EQ PUSH2 0x4DF JUMPI DUP1 PUSH4 0xBA51A6DF EQ PUSH2 0x4F4 JUMPI DUP1 PUSH4 0xC01A8C84 EQ PUSH2 0x50C JUMPI DUP1 PUSH4 0xC6427474 EQ PUSH2 0x524 JUMPI DUP1 PUSH4 0xD38F2D82 EQ PUSH2 0x58D JUMPI DUP1 PUSH4 0xD74F8EDD EQ PUSH2 0x5A5 JUMPI DUP1 PUSH4 0xDC8452CD EQ PUSH2 0x5BA JUMPI DUP1 PUSH4 0xE20056E6 EQ PUSH2 0x5CF JUMPI DUP1 PUSH4 0xEE22610B EQ PUSH2 0x5F6 JUMPI JUMPDEST PUSH1 0x0 CALLVALUE GT ISZERO PUSH2 0x185 JUMPI PUSH1 0x40 DUP1 MLOAD CALLVALUE DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0xE1FFFCC4923D04B559F4D29A8BFC6CDA04EB5B0D3C460751C2402C5C5CC9109C SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x193 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH1 0x4 CALLDATALOAD PUSH2 0x60E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x636 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1E8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x79B JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x200 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x86A JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x235 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x24 CALLDATALOAD AND PUSH2 0x87F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x259 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x89F JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x280 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD ISZERO ISZERO PUSH1 0x24 CALLDATALOAD ISZERO ISZERO PUSH2 0x8A5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x29F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 DUP1 CALLDATALOAD DUP1 DUP3 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x215 SWAP5 CALLDATASIZE SWAP5 SWAP3 SWAP4 PUSH1 0x24 SWAP4 SWAP3 DUP5 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x911 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x9B4 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x310 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0xBC7 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x331 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH2 0xCC5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x349 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0xD42 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x361 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0xD89 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x379 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x385 PUSH1 0x4 CALLDATALOAD PUSH2 0xDF8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP6 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x20 ADD DUP5 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x3EA JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x3D2 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x417 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP6 POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x434 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH2 0xEB6 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 DUP2 ADD SWAP2 MUL DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x479 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x461 JUMP JUMPDEST POP POP POP POP SWAP1 POP ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x499 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH1 0x24 CALLDATALOAD PUSH1 0x44 CALLDATALOAD ISZERO ISZERO PUSH1 0x64 CALLDATALOAD ISZERO ISZERO PUSH2 0xF19 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4BE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH2 0x1052 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4D3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH2 0x1061 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4EB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x11DA JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x500 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x11E0 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x518 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x1257 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x530 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 PUSH1 0x44 CALLDATALOAD DUP2 DUP2 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x262 SWAP5 DUP3 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP5 PUSH1 0x24 DUP1 CALLDATALOAD SWAP6 CALLDATASIZE SWAP6 SWAP5 PUSH1 0x64 SWAP5 SWAP3 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x133E SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x599 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0x135D JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x136F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5C6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x1374 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH2 0x137A JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x602 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x14E0 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x61C JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 POP DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x644 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x66D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE SWAP2 POP JUMPDEST PUSH1 0x3 SLOAD PUSH1 0x0 NOT ADD DUP3 LT ISZERO PUSH2 0x748 JUMPI DUP3 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x6B7 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x73D JUMPI PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT DUP2 ADD SWAP1 DUP2 LT PUSH2 0x6E4 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x70A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x748 JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH2 0x690 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT ADD SWAP1 PUSH2 0x75B SWAP1 DUP3 PUSH2 0x1774 JUMP JUMPDEST POP PUSH1 0x3 SLOAD PUSH1 0x4 SLOAD GT ISZERO PUSH2 0x774 JUMPI PUSH1 0x3 SLOAD PUSH2 0x774 SWAP1 PUSH2 0x11E0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP5 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7B9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP4 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7E5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD DUP5 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x806 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x810 DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x81A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE DUP1 DUP4 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE MLOAD DUP9 SWAP3 PUSH32 0xF6A317157440607F36269043EB55F1287A5A19BA2216AFEAB88CD46CBCFB88E9 SWAP2 LOG3 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x0 SWAP3 DUP4 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 SWAP1 SWAP2 MSTORE SWAP1 DUP3 MSTORE SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0x90A JUMPI DUP4 DUP1 ISZERO PUSH2 0x8D2 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0x8F6 JUMPI POP DUP3 DUP1 ISZERO PUSH2 0x8F6 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0x902 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0x8A9 JUMP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x72656D6F7665417574686F72697A656441646472657373286164647265737329 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 KECCAK256 PUSH1 0x0 SWAP1 DUP2 JUMPDEST PUSH1 0x4 DUP2 LT ISZERO PUSH2 0x9A8 JUMPI DUP2 DUP2 PUSH1 0x4 DUP2 LT PUSH2 0x95D JUMPI INVALID JUMPDEST BYTE PUSH1 0xF8 PUSH1 0x2 EXP MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x97C JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP2 ADD ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND EQ PUSH2 0x9A0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 ADD PUSH2 0x948 JUMP JUMPDEST PUSH1 0x1 SWAP3 POP JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x9D5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x9DF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x9EA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x8 SLOAD DUP2 SLOAD DUP7 SWAP3 SWAP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP2 DUP3 AND SWAP2 AND EQ PUSH2 0xA17 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x2 DUP2 DUP2 ADD DUP1 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x1 DUP5 AND ISZERO PUSH2 0x100 MUL PUSH1 0x0 NOT ADD SWAP1 SWAP4 AND SWAP5 SWAP1 SWAP5 DIV PUSH1 0x1F DUP2 ADD DUP4 SWAP1 DIV DUP4 MUL DUP6 ADD DUP4 ADD SWAP1 SWAP2 MSTORE DUP1 DUP5 MSTORE PUSH2 0xAAC SWAP4 SWAP3 SWAP2 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xAA2 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA77 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAA2 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA85 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP PUSH2 0x911 JUMP JUMPDEST ISZERO ISZERO PUSH2 0xAB7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP12 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0xB60 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB35 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB60 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB43 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0xB99 JUMPI PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0xBBF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP6 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP POP JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xBD3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0xBFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0xC11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x1 ADD PUSH1 0x4 SLOAD PUSH1 0x32 DUP3 GT DUP1 PUSH2 0xC2B JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0xC34 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0xC3D JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0xC47 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE PUSH1 0x3 DUP1 SLOAD SWAP2 DUP3 ADD DUP2 SSTORE DUP4 MSTORE PUSH32 0xC2575A0E9E593C00F959F8C92F12DB2869C3395A3B0502D05E2516446F71F85B ADD DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND DUP5 OR SWAP1 SSTORE MLOAD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x9AD JUMPI PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xCF3 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xD27 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x4 SLOAD DUP3 EQ ISZERO PUSH2 0xD3A JUMPI PUSH1 0x1 SWAP3 POP PUSH2 0x9AD JUMP JUMPDEST PUSH1 0x1 ADD PUSH2 0xCCA JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xD4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 DUP2 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP3 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xD1C9101A34FEFF75CCCEF14A28785A0279CB0B49C1F321F21F5F422E746B4377 SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0xDF2 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xDB6 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xDEA JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0xD8D JUMP JUMPDEST POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP2 DUP2 MSTORE SWAP2 DUP2 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 DUP1 SLOAD PUSH1 0x1 DUP1 DUP4 ADD SLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD DUP8 MLOAD PUSH2 0x100 SWAP6 DUP3 AND ISZERO SWAP6 SWAP1 SWAP6 MUL PUSH1 0x0 NOT ADD AND SWAP2 SWAP1 SWAP2 DIV PUSH1 0x1F DUP2 ADD DUP9 SWAP1 DIV DUP9 MUL DUP5 ADD DUP9 ADD SWAP1 SWAP7 MSTORE DUP6 DUP4 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP1 SWAP5 SWAP2 SWAP3 SWAP2 SWAP1 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xEA3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xE78 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xEA3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xE86 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP PUSH1 0x3 SWAP1 SWAP4 ADD SLOAD SWAP2 SWAP3 POP POP PUSH1 0xFF AND DUP5 JUMP JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD DUP1 ISZERO PUSH2 0xF0E JUMPI PUSH1 0x20 MUL DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xEF0 JUMPI JUMPDEST POP POP POP POP POP SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x5 SLOAD PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xF4B JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0xFD2 JUMPI DUP6 DUP1 ISZERO PUSH2 0xF80 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0xFA4 JUMPI POP DUP5 DUP1 ISZERO PUSH2 0xFA4 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0xFCA JUMPI DUP1 DUP4 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xFB8 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0xF57 JUMP JUMPDEST DUP8 DUP8 SUB PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xFFE JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP DUP8 SWAP1 POP JUMPDEST DUP7 DUP2 LT ISZERO PUSH2 0x1047 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP10 DUP4 SUB DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1035 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1005 JUMP JUMPDEST POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x8 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x1096 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x1153 JUMPI PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x10CB JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0x114B JUMPI PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x1106 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP2 AND SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP2 LT PUSH2 0x112C JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0x10A2 JUMP JUMPDEST DUP2 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x117D JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP2 DUP2 LT ISZERO PUSH2 0x11D2 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x119B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x11B3 JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1185 JUMP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x5 SLOAD DUP2 JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0x11EC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 SLOAD DUP2 PUSH1 0x32 DUP3 GT DUP1 PUSH2 0x11FE JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0x1207 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0x1210 JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0x121A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x4 DUP4 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xA3F1EE9126A074D9326C682F561767F710E927FAA811F7A99829D49DC421797A SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x1275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND ISZERO ISZERO PUSH2 0x129A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP5 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x12C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x12CF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x12D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 DUP2 DUP2 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 CALLER DUP1 DUP7 MSTORE SWAP3 MSTORE DUP1 DUP5 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SWAP4 OR SWAP1 SWAP3 SSTORE SWAP1 MLOAD DUP9 SWAP3 PUSH32 0x4A504A94899432A9846E1AA406DCEB1BCFD538BB839071D49D1E5E23F5BE30EF SWAP2 LOG3 PUSH2 0x132F DUP7 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0xBBF JUMPI PUSH2 0xBBF DUP7 TIMESTAMP PUSH2 0x1646 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x134B DUP5 DUP5 DUP5 PUSH2 0x1691 JUMP JUMPDEST SWAP1 POP PUSH2 0x1356 DUP2 PUSH2 0x1257 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x32 DUP2 JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x1388 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x13B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x13D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 SWAP3 POP JUMPDEST PUSH1 0x3 SLOAD DUP4 LT ISZERO PUSH2 0x146A JUMPI DUP5 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1401 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x145F JUMPI DUP4 PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x142C JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x146A JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP3 ADD SWAP2 PUSH2 0x13DE JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP1 DUP7 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT SWAP1 DUP2 AND SWAP1 SWAP2 SSTORE SWAP4 DUP9 AND DUP3 MSTORE DUP1 DUP3 KECCAK256 DUP1 SLOAD SWAP1 SWAP5 AND PUSH1 0x1 OR SWAP1 SWAP4 SSTORE SWAP2 MLOAD SWAP1 SWAP2 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 LOG2 PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x1501 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x150B DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x1516 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 SLOAD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP6 SWAP2 ADD TIMESTAMP LT ISZERO PUSH2 0x1537 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP11 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0x15E0 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x15B5 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x15E0 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x15C3 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0x1619 JUMPI PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0x163F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP5 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP2 DUP3 SWAP1 KECCAK256 DUP4 SWAP1 SSTORE DUP2 MLOAD DUP4 DUP2 MSTORE SWAP2 MLOAD DUP5 SWAP3 PUSH32 0xB237AFE65F1514FD7EA3F923EA4FE792BDD07000A912B6CD1602A8E7F573C8D SWAP3 SWAP1 DUP3 SWAP1 SUB ADD SWAP1 LOG2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0x16A9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x5 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP9 DUP2 AND DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 ADD DUP10 DUP2 MSTORE DUP4 DUP6 ADD DUP10 DUP2 MSTORE PUSH1 0x0 PUSH1 0x60 DUP7 ADD DUP2 SWAP1 MSTORE DUP8 DUP2 MSTORE DUP1 DUP5 MSTORE SWAP6 SWAP1 SWAP6 KECCAK256 DUP5 MLOAD DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND SWAP5 AND SWAP4 SWAP1 SWAP4 OR DUP4 SSTORE MLOAD PUSH1 0x1 DUP4 ADD SSTORE SWAP3 MLOAD DUP1 MLOAD SWAP5 SWAP7 POP SWAP2 SWAP4 SWAP1 SWAP3 PUSH2 0x171C SWAP3 PUSH1 0x2 DUP6 ADD SWAP3 SWAP2 ADD SWAP1 PUSH2 0x179D JUMP JUMPDEST POP PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD MLOAD PUSH1 0x3 SWAP1 SWAP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP2 ISZERO ISZERO SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE PUSH1 0x40 MLOAD DUP3 SWAP1 PUSH32 0xC0BA8FE4B176C1714197D43B9CC6BCF797A4A7461C5FE8D0EF6E184AE7601E51 SWAP1 PUSH1 0x0 SWAP1 LOG2 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 GT ISZERO PUSH2 0x1798 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x20 SWAP1 KECCAK256 PUSH2 0x1798 SWAP2 DUP2 ADD SWAP1 DUP4 ADD PUSH2 0x181B JUMP JUMPDEST POP POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x17DE JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x180B JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x180B JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x180B JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x17F0 JUMP JUMPDEST POP PUSH2 0x1817 SWAP3 SWAP2 POP PUSH2 0x181B JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH2 0xF16 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1817 JUMPI PUSH1 0x0 DUP2 SSTORE PUSH1 0x1 ADD PUSH2 0x1821 JUMP STOP MSTORE PUSH5 0x41BB6C1ABA EXTCODECOPY SWAP11 0x4a PUSH13 0xA1D6545DA9C2333C8C48343EF3 SWAP9 0xeb DUP6 DUP14 PUSH19 0xB79236F39E6E1EB0EDCF53C221607B54B00CD2 DUP16 BALANCE SWAP7 INVALID 0xd0 LOG2 0x49 SWAP5 0xdc ADDRESS DUP12 DUP16 PUSH2 0x1B68 0x2d CALLER 0xe1 RETURNDATACOPY 0xcb SLOAD 0xc3 SMOD PUSH14 0x8E8BB8C2881800A4D972B792045F STATICCALL 0xe9 DUP16 0xdf 0x46 0xdf CALLDATASIZE 0x5f 0xed PUSH22 0x8001553A916EF2F495D26A907CC54D96ED840D7BDA71 0xe7 BALANCE SWAP5 0xbf GAS SWAP14 0xf7 0xa7 PUSH12 0x90A165627A7A723058200853 0xbb 0x25 XOR PUSH1 0xC9 0x29 GASLIMIT LOG3 0xc9 0x4e 0xbb 0xaa DUP7 0xcb 0xe3 0xf8 0xb7 0xed 0x5e SWAP6 0xb4 DUP5 DELEGATECALL 0x28 PUSH22 0x2638C133800029000000000000000000000000000000 ", + "sourceMap": + "714:2422:2:-;;;;;;;;;-1:-1:-1;;;714:2422:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2519:1:0;2507:9;:13;2503:61;;;2534:30;;;2554:9;2534:30;;;;2542:10;;2534:30;;;;;;;;;;2503:61;714:2422:2;936:23:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;936:23:0;;;;;;;;;-1:-1:-1;;;;;936:23:0;;;;;;;;;;;;;;3711:460;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3711:460:0;-1:-1:-1;;;;;3711:460:0;;;;;3196:332:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3196:332:1;;;;;890:40:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;890:40:0;-1:-1:-1;;;;;890:40:0;;;;;;;;;;;;;;;;;;;;;;;820:64;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;820:64:0;;;-1:-1:-1;;;;;820:64:0;;;;;1049:29:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1049:29:1;;;;;;;;;;;;;;;;;;;;9136:319:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;9136:319:0;;;;;;;;;;;2774:360:2;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2774:360:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2774:360:2;;-1:-1:-1;2774:360:2;;-1:-1:-1;;;;;;;2774:360:2;2058:502;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2058:502:2;;;;;3311:277:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3311:277:0;-1:-1:-1;;;;;3311:277:0;;;;;7304:337;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7304:337:0;;;;;2321:186:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2321:186:1;;;;;8622:252:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;8622:252:0;;;;;765:49;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;765:49:0;;;;;;;;;;-1:-1:-1;;;;;765:49:0;-1:-1:-1;;;;;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9539:115;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9539:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;9539:115:0;;;;;;;;;;;;;;;;;10757:676;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;10757:676:0;;;;;;;;;;;;;;;816:44:2;;8:9:-1;5:2;;;30:1;27;20:12;5:2;816:44:2;;;;9833:575:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;9833:575:0;;;;;991:28;;8:9:-1;5:2;;;30:1;27;20:12;5:2;991:28:0;;;;4990:207;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4990:207:0;;;;;2613:459:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2613:459:1;;;;;5456:244:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;5456:244:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5456:244:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5456:244:0;;-1:-1:-1;5456:244:0;;-1:-1:-1;;;;;;;5456:244:0;1085:47:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;1085:47:1;;;;;217:41:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;217:41:0;;;;965:20;;8:9:-1;5:2;;;30:1;27;20:12;5:2;965:20:0;;;;4370:449;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4370:449:0;-1:-1:-1;;;;;4370:449:0;;;;;;;;;;3642:472:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3642:472:1;;;;;936:23:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;936:23:0;;-1:-1:-1;936:23:0;:::o;3711:460::-;3859:6;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;-1:-1:-1;;;;;1420:14:0;;;;;;:7;:14;;;;;;3801:5;;1420:14;;1419:15;1415:38;;;1448:5;;;1415:38;-1:-1:-1;;;;;3822:14:0;;3839:5;3822:14;;;:7;:14;;;;;:22;;-1:-1:-1;;3822:22:0;;;3839:5;-1:-1:-1;3854:170:0;3871:6;:13;-1:-1:-1;;3871:17:0;3869:19;;3854:170;;;3924:5;-1:-1:-1;;;;;3911:18:0;:6;3918:1;3911:9;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3911:9:0;:18;3907:117;;;3961:6;3968:13;;-1:-1:-1;;3968:17:0;;;3961:25;;;;;;;;;;;;;;;;3949:6;:9;;-1:-1:-1;;;;;3961:25:0;;;;3956:1;;3949:9;;;;;;;;;;;;;;:37;;;;;-1:-1:-1;;;;;3949:37:0;;;;;-1:-1:-1;;;;;3949:37:0;;;;;;4004:5;;3907:117;3890:3;;;;;3854:170;;;4033:6;:18;;-1:-1:-1;;4033:18:0;;;;;;:::i;:::-;-1:-1:-1;4076:6:0;:13;4065:8;;:24;4061:74;;;4121:6;:13;4103:32;;:17;:32::i;:::-;4145:19;;-1:-1:-1;;;;;4145:19:0;;;-1:-1:-1;;;;;;;;;;;4145:19:0;;;;1242:1;3711:460;;:::o;3196:332:1:-;3279:10;1420:14:0;;;;:7;:14;;;;;;;;1419:15;1415:38;;;1448:5;;;1415:38;1694:28;;;;:13;:28;;;;;;;;3324:10:1;1694:35:0;;;;;;;;;3309:13:1;;3324:10;1694:35:0;;1693:36;1689:59;;;1743:5;;;1689:59;1976:12;:27;;;;;;;;;;:36;;;3356:13:1;;1976:36:0;;1972:59;;;2026:5;;;1972:59;3397:13:1;1205:26;1217:13;1205:11;:26::i;:::-;1204:27;1196:36;;;;;;3469:5;3426:28;;;:13;:28;;;;;;;;3455:10;3426:40;;;;;;;;:48;;-1:-1:-1;;3426:48:1;;;3484:37;3440:13;;3484:37;;;2041:1:0;1758;1463;;3196:332:1;;:::o;890:40:0:-;;;;;;;;;;;;;;;:::o;820:64::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1049:29:1:-;;;;:::o;9136:319:0:-;9243:10;;9269:179;9286:16;;9284:1;:18;9269:179;;;9328:7;:36;;;;-1:-1:-1;9340:12:0;:15;;;;;;;;;;:24;;;;;9339:25;9328:36;:92;;;;9384:8;:36;;;;-1:-1:-1;9396:12:0;:15;;;;;;;;;;:24;;;;;9384:36;9321:127;;;9447:1;9438:10;;;;9321:127;9304:3;;9269:179;;;9136:319;;;;;:::o;2774:360:2:-;2947:40;;;;;;;;;;;;;;;;2878:4;;;2998:109;3019:1;3015;:5;2998:109;;;3060:32;3093:1;3060:35;;;;;;;;-1:-1:-1;;;3060:35:2;-1:-1:-1;;;;;3049:46:2;;:4;3054:1;3049:7;;;;;;;;;;;;;;;-1:-1:-1;;;3049:7:2;;;;;-1:-1:-1;;;;;;3049:46:2;;3041:55;;;;;;3022:3;;2998:109;;;3123:4;3116:11;;2774:360;;;;;;:::o;2058:502::-;2274:22;1976:27:0;;;;;;;;;;:36;;;2153:13:2;;1976:36:0;;1972:59;;;2026:5;;;1972:59;2191:13:2;1318:26:1;1330:13;1318:11;:26::i;:::-;1310:35;;;;;;;;937:22:2;962:27;;;;;;;;;;1025:29;;1007:14;;2245:13;;962:27;-1:-1:-1;;;;;1007:14:2;;;1025:29;;1007:47;999:56;;;;;;1107:7;;;;1073:42;;;;;;;;;;;;-1:-1:-1;;1073:42:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1107:7;1073:42;;1107:7;1073:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:33;:42::i;:::-;1065:51;;;;;;;;2299:12;:27;;;;;;;;;;;;2336:11;;;:18;;-1:-1:-1;;2336:18:2;2350:4;2336:18;;;;;;2368:14;;2394:8;;;;2368:44;;2404:7;;;;2368:44;;2299:27;;-1:-1:-1;;;;;;2368:14:2;;;;2394:8;2404:7;;2368:44;;;;2404:7;;-1:-1:-1;;2368:44:2;;;;2336:18;2368:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2364:190;;;2426:24;;2436:13;;-1:-1:-1;;;;;;;;;;;2426:24:2;;;;2364:190;;;2479:31;;2496:13;;-1:-1:-1;;;;;;;;;;;2479:31:2;;;;2524:11;;;:19;;-1:-1:-1;;2524:19:2;;;2364:190;1355:1:1;;2041::0;2058:502:2;;;:::o;3311:277:0:-;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;-1:-1:-1;;;;;1312:14:0;;;;;;:7;:14;;;;;;3404:5;;1312:14;;1308:37;;;1340:5;;;1308:37;3427:5;-1:-1:-1;;;;;2104:13:0;;;2100:36;;;2131:5;;;2100:36;3459:6;:13;;;;3475:1;3459:17;3478:8;;256:2;2236:10;:28;:66;;;;2292:10;2280:9;:22;2236:66;:96;;;-1:-1:-1;2318:14:0;;2236:96;:127;;;-1:-1:-1;2348:15:0;;2236:127;2229:153;;;2377:5;;;2229:153;-1:-1:-1;;;;;3502:14:0;;;;;;:7;:14;;;;;;:21;;-1:-1:-1;;3502:21:0;3519:4;3502:21;;;;;;3533:6;27:10:-1;;23:18;;;45:23;;3533:18:0;;;;;;-1:-1:-1;;;;;;3533:18:0;;;;;3561:20;-1:-1:-1;;;;;;;;;;;3561:20:0;3502:14;3561:20;2146:1;;1355;1242;3311:277;:::o;7304:337::-;7394:4;;;7438:197;7455:6;:13;7453:15;;7438:197;;;7493:28;;;;:13;:28;;;;;7522:6;:9;;7493:28;;;7529:1;;7522:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7522:9:0;7493:39;;;;;;;;;;;;;;;7489:71;;;7559:1;7550:10;;;;7489:71;7587:8;;7578:5;:17;7574:50;;;7620:4;7613:11;;;;7574:50;7470:3;;7438:197;;2321:186:1;1186:10:0;1208:4;1186:27;1182:50;;1227:5;;;1182:50;2418:17:1;:38;;;2466:34;;;;;;;;;;;;;;;;;2321:186;:::o;8622:252:0:-;8721:10;;8747:120;8764:6;:13;8762:15;;8747:120;;;8800:28;;;;:13;:28;;;;;8829:6;:9;;8800:28;;;8836:1;;8829:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8829:9:0;8800:39;;;;;;;;;;;;;;;8796:71;;;8866:1;8857:10;;;;8796:71;8779:3;;8747:120;;;8622:252;;;;:::o;765:49::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;765:49:0;;;;;;;-1:-1:-1;;765:49:0;;;:::o;9539:115::-;9609:9;9641:6;9634:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;9634:13:0;;;;;;;;;;;;;;;;;;;;;;;9539:115;;:::o;10757:676::-;10882:22;10920:32;10993:10;11017:6;10966:16;;10955:28;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10955:28:0;;10920:63;;11006:1;10993:14;;11040:1;11038:3;;11033:250;11045:16;;11043:1;:18;11033:250;;;11087:7;:36;;;;-1:-1:-1;11099:12:0;:15;;;;;;;;;;:24;;;;;11098:25;11087:36;:92;;;;11143:8;:36;;;;-1:-1:-1;11155:12:0;:15;;;;;;;;;;:24;;;;;11143:36;11080:203;;;11239:1;11211:18;11230:5;11211:25;;;;;;;;;;;;;;;;;;:29;11267:1;11258:10;;;;;11080:203;11063:3;;11033:250;;;11326:4;11321:2;:9;11310:21;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;11310:21:0;;11292:39;;11348:4;11346:6;;11341:85;11356:2;11354:1;:4;11341:85;;;11405:18;11424:1;11405:21;;;;;;;;;;;;;;;;;;11377:15;11397:4;11393:1;:8;11377:25;;;;;;;;;;;;;;;;;;:49;11360:3;;11341:85;;;10757:676;;;;;;;;;:::o;816:44:2:-;;;-1:-1:-1;;;;;816:44:2;;:::o;9833:575:0:-;9928:24;9968:34;10043:10;10067:6;10019;:13;;;;10005:28;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10005:28:0;;9968:65;;10056:1;10043:14;;10090:1;10088:3;;10083:186;10095:6;:13;10093:15;;10083:186;;;10131:28;;;;:13;:28;;;;;10160:6;:9;;10131:28;;;10167:1;;10160:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10160:9:0;10131:39;;;;;;;;;;;;;;;10127:142;;;10217:6;:9;;10224:1;;10217:9;;;;;;;;;;;;;;;;10190:24;;-1:-1:-1;;;;;10217:9:0;;;;10190:17;;10208:5;;10190:24;;;;;;-1:-1:-1;;;;;10190:36:0;;;:24;;;;;;;;;;:36;10253:1;10244:10;;;;;10127:142;10110:3;;10083:186;;;10309:5;10295:20;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10295:20:0;;10278:37;;10332:1;10330:3;;10325:76;10337:5;10335:1;:7;10325:76;;;10381:17;10399:1;10381:20;;;;;;;;;;;;;;;;;;10361:14;10376:1;10361:17;;;;;;;;;;-1:-1:-1;;;;;10361:40:0;;;:17;;;;;;;;;;:40;10344:3;;10325:76;;;9833:575;;;;;;:::o;991:28::-;;;;:::o;4990:207::-;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;5092:6;:13;5107:9;256:2;2236:28;;;:66;;;2292:10;2280:9;:22;2236:66;:96;;;-1:-1:-1;2318:14:0;;2236:96;:127;;;-1:-1:-1;2348:15:0;;2236:127;2229:153;;;2377:5;;;2229:153;5132:8;:20;;;5162:28;;;;;;;;;;;;;;;;;1242:1;;4990:207;:::o;2613:459:1:-;2696:10;1420:14:0;;;;:7;:14;;;;;;;;1419:15;1415:38;;;1448:5;;;1415:38;1538:12;:27;;;;;;;;;;:39;2734:13:1;;-1:-1:-1;;;;;1538:39:0;:44;1534:67;;;1596:5;;;1534:67;1843:28;;;;:13;:28;;;;;;;;2785:10:1;1843:35:0;;;;;;;;;2770:13:1;;2785:10;1843:35:0;;1839:58;;;1892:5;;;1839:58;2823:13:1;1205:26;1217:13;1205:11;:26::i;:::-;1204:27;1196:36;;;;;;2852:28;;;;2895:4;2852:28;;;;;;;;2881:10;2852:40;;;;;;;;:47;;-1:-1:-1;;2852:47:1;;;;;;;2909:39;;2866:13;;2909:39;;;2962:26;2974:13;2962:11;:26::i;:::-;2958:108;;;3004:51;3024:13;3039:15;3004:19;:51::i;5456:244:0:-;5560:18;5610:40;5625:11;5638:5;5645:4;5610:14;:40::i;:::-;5594:56;;5660:33;5679:13;5660:18;:33::i;:::-;5456:244;;;;;:::o;1085:47:1:-;;;;;;;;;;;;;:::o;217:41:0:-;256:2;217:41;:::o;965:20::-;;;;:::o;4370:449::-;4541:6;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;-1:-1:-1;;;;;1420:14:0;;;;;;:7;:14;;;;;;4479:5;;1420:14;;1419:15;1415:38;;;1448:5;;;1415:38;-1:-1:-1;;;;;1312:14:0;;;;;;:7;:14;;;;;;4512:8;;1312:14;;1308:37;;;1340:5;;;1308:37;4548:1;4541:8;;4536:149;4553:6;:13;4551:15;;4536:149;;;4602:5;-1:-1:-1;;;;;4589:18:0;:6;4596:1;4589:9;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4589:9:0;:18;4585:100;;;4639:8;4627:6;4634:1;4627:9;;;;;;;;;;;;;;;;;;:20;;;;;-1:-1:-1;;;;;4627:20:0;;;;;-1:-1:-1;;;;;4627:20:0;;;;;;4665:5;;4585:100;4568:3;;;;;4536:149;;;-1:-1:-1;;;;;4694:14:0;;;4711:5;4694:14;;;:7;:14;;;;;;:22;;-1:-1:-1;;4694:22:0;;;;;;4726:17;;;;;;;;:24;;;;;4694:22;4726:24;;;;4760:19;;4694:14;;-1:-1:-1;;;;;;;;;;;4760:19:0;;4789:23;;-1:-1:-1;;;;;4789:23:0;;;-1:-1:-1;;;;;;;;;;;4789:23:0;;;;1463:1;1242;4370:449;;;:::o;3642:472:1:-;3828:22;1976:27:0;;;;;;;;;;:36;;;3725:13:1;;1976:36:0;;1972:59;;;2026:5;;;1972:59;3763:13:1;1318:26;1330:13;1318:11;:26::i;:::-;1310:35;;;;;;;;1483:17;;1448:32;;;;:17;:32;;;;;;3799:13;;1448:52;1429:15;:71;;1421:80;;;;;;3853:12;:27;;;;;;;;;;;;3890:11;;;:18;;-1:-1:-1;;3890:18:1;3904:4;3890:18;;;;;;3922:14;;3948:8;;;;3922:44;;3958:7;;;;3922:44;;3853:27;;-1:-1:-1;;;;;;3922:14:1;;;;3948:8;3958:7;;3922:44;;;;3958:7;;-1:-1:-1;;3922:44:1;;;;3890:18;3922:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3918:190;;;3980:24;;3990:13;;-1:-1:-1;;;;;;;;;;;3980:24:1;;;;3918:190;;;4033:31;;4050:13;;-1:-1:-1;;;;;;;;;;;4033:31:1;;;;4078:11;;;:19;;-1:-1:-1;;4078:19:1;;;3918:190;1355:1;2041::0;3642:472:1;;;:::o;4224:223::-;4327:32;;;;:17;:32;;;;;;;;;:51;;;4388:52;;;;;;;4345:13;;4388:52;;;;;;;;;4224:223;;:::o;7974:451:0:-;8106:18;8076:11;-1:-1:-1;;;;;2104:13:0;;;2100:36;;;2131:5;;;2100:36;8156:16;;8212:140;;;;;;;;-1:-1:-1;;;;;8212:140:0;;;;;;;;;;;;;;;;;;-1:-1:-1;8212:140:0;;;;;;8182:27;;;;;;;;;;:170;;;;-1:-1:-1;;;;;;8182:170:0;;;;;;;;;;-1:-1:-1;8182:170:0;;;;;;;8156:16;;-1:-1:-1;8212:140:0;;8182:27;;:170;;;;;;;;;;:::i;:::-;-1:-1:-1;8182:170:0;;;;;;;;;;;;-1:-1:-1;;8182:170:0;;;;;;;;;;8362:16;:21;;-1:-1:-1;8362:21:0;;;8393:25;;8404:13;;8393:25;;-1:-1:-1;;8393:25:0;7974:451;;;;;;:::o;714:2422:2:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;714:2422:2;;;-1:-1:-1;714:2422:2;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;" + } + } + }, + "sources": { + "current/multisig/MultiSigWallet/MultiSigWallet.sol": { + "id": 0 + }, + "current/multisig/MultiSigWalletWithTimeLock/MultiSigWalletWithTimeLock.sol": { + "id": 1 + }, + "current/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol": { + "id": 2 + } + }, + "sourceCodes": { + "current/multisig/MultiSigWallet/MultiSigWallet.sol": + "pragma solidity ^0.4.10;\n\n/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.\n/// @author Stefan George - \ncontract MultiSigWallet {\n\n uint constant public MAX_OWNER_COUNT = 50;\n\n event Confirmation(address indexed sender, uint indexed transactionId);\n event Revocation(address indexed sender, uint indexed transactionId);\n event Submission(uint indexed transactionId);\n event Execution(uint indexed transactionId);\n event ExecutionFailure(uint indexed transactionId);\n event Deposit(address indexed sender, uint value);\n event OwnerAddition(address indexed owner);\n event OwnerRemoval(address indexed owner);\n event RequirementChange(uint required);\n\n mapping (uint => Transaction) public transactions;\n mapping (uint => mapping (address => bool)) public confirmations;\n mapping (address => bool) public isOwner;\n address[] public owners;\n uint public required;\n uint public transactionCount;\n\n struct Transaction {\n address destination;\n uint value;\n bytes data;\n bool executed;\n }\n\n modifier onlyWallet() {\n if (msg.sender != address(this))\n throw;\n _;\n }\n\n modifier ownerDoesNotExist(address owner) {\n if (isOwner[owner])\n throw;\n _;\n }\n\n modifier ownerExists(address owner) {\n if (!isOwner[owner])\n throw;\n _;\n }\n\n modifier transactionExists(uint transactionId) {\n if (transactions[transactionId].destination == 0)\n throw;\n _;\n }\n\n modifier confirmed(uint transactionId, address owner) {\n if (!confirmations[transactionId][owner])\n throw;\n _;\n }\n\n modifier notConfirmed(uint transactionId, address owner) {\n if (confirmations[transactionId][owner])\n throw;\n _;\n }\n\n modifier notExecuted(uint transactionId) {\n if (transactions[transactionId].executed)\n throw;\n _;\n }\n\n modifier notNull(address _address) {\n if (_address == 0)\n throw;\n _;\n }\n\n modifier validRequirement(uint ownerCount, uint _required) {\n if ( ownerCount > MAX_OWNER_COUNT\n || _required > ownerCount\n || _required == 0\n || ownerCount == 0)\n throw;\n _;\n }\n\n /// @dev Fallback function allows to deposit ether.\n function()\n payable\n {\n if (msg.value > 0)\n Deposit(msg.sender, msg.value);\n }\n\n /*\n * Public functions\n */\n /// @dev Contract constructor sets initial owners and required number of confirmations.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n function MultiSigWallet(address[] _owners, uint _required)\n public\n validRequirement(_owners.length, _required)\n {\n for (uint i=0; i<_owners.length; i++) {\n if (isOwner[_owners[i]] || _owners[i] == 0)\n throw;\n isOwner[_owners[i]] = true;\n }\n owners = _owners;\n required = _required;\n }\n\n /// @dev Allows to add a new owner. Transaction has to be sent by wallet.\n /// @param owner Address of new owner.\n function addOwner(address owner)\n public\n onlyWallet\n ownerDoesNotExist(owner)\n notNull(owner)\n validRequirement(owners.length + 1, required)\n {\n isOwner[owner] = true;\n owners.push(owner);\n OwnerAddition(owner);\n }\n\n /// @dev Allows to remove an owner. Transaction has to be sent by wallet.\n /// @param owner Address of owner.\n function removeOwner(address owner)\n public\n onlyWallet\n ownerExists(owner)\n {\n isOwner[owner] = false;\n for (uint i=0; i owners.length)\n changeRequirement(owners.length);\n OwnerRemoval(owner);\n }\n\n /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.\n /// @param owner Address of owner to be replaced.\n /// @param owner Address of new owner.\n function replaceOwner(address owner, address newOwner)\n public\n onlyWallet\n ownerExists(owner)\n ownerDoesNotExist(newOwner)\n {\n for (uint i=0; i\ncontract MultiSigWalletWithTimeLock is MultiSigWallet {\n\n event ConfirmationTimeSet(uint indexed transactionId, uint confirmationTime);\n event TimeLockChange(uint secondsTimeLocked);\n\n uint public secondsTimeLocked;\n\n mapping (uint => uint) public confirmationTimes;\n\n modifier notFullyConfirmed(uint transactionId) {\n require(!isConfirmed(transactionId));\n _;\n }\n\n modifier fullyConfirmed(uint transactionId) {\n require(isConfirmed(transactionId));\n _;\n }\n\n modifier pastTimeLock(uint transactionId) {\n require(block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked);\n _;\n }\n\n /*\n * Public functions\n */\n\n /// @dev Contract constructor sets initial owners, required number of confirmations, and time lock.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.\n function MultiSigWalletWithTimeLock(address[] _owners, uint _required, uint _secondsTimeLocked)\n public\n MultiSigWallet(_owners, _required)\n {\n secondsTimeLocked = _secondsTimeLocked;\n }\n\n /// @dev Changes the duration of the time lock for transactions.\n /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.\n function changeTimeLock(uint _secondsTimeLocked)\n public\n onlyWallet\n {\n secondsTimeLocked = _secondsTimeLocked;\n TimeLockChange(_secondsTimeLocked);\n }\n\n /// @dev Allows an owner to confirm a transaction.\n /// @param transactionId Transaction ID.\n function confirmTransaction(uint transactionId)\n public\n ownerExists(msg.sender)\n transactionExists(transactionId)\n notConfirmed(transactionId, msg.sender)\n notFullyConfirmed(transactionId)\n {\n confirmations[transactionId][msg.sender] = true;\n Confirmation(msg.sender, transactionId);\n if (isConfirmed(transactionId)) {\n setConfirmationTime(transactionId, block.timestamp);\n }\n }\n\n /// @dev Allows an owner to revoke a confirmation for a transaction.\n /// @param transactionId Transaction ID.\n function revokeConfirmation(uint transactionId)\n public\n ownerExists(msg.sender)\n confirmed(transactionId, msg.sender)\n notExecuted(transactionId)\n notFullyConfirmed(transactionId)\n {\n confirmations[transactionId][msg.sender] = false;\n Revocation(msg.sender, transactionId);\n }\n\n /// @dev Allows anyone to execute a confirmed transaction.\n /// @param transactionId Transaction ID.\n function executeTransaction(uint transactionId)\n public\n notExecuted(transactionId)\n fullyConfirmed(transactionId)\n pastTimeLock(transactionId)\n {\n Transaction storage tx = transactions[transactionId];\n tx.executed = true;\n if (tx.destination.call.value(tx.value)(tx.data))\n Execution(transactionId);\n else {\n ExecutionFailure(transactionId);\n tx.executed = false;\n }\n }\n\n /*\n * Internal functions\n */\n\n /// @dev Sets the time of when a submission first passed.\n function setConfirmationTime(uint transactionId, uint confirmationTime)\n internal\n {\n confirmationTimes[transactionId] = confirmationTime;\n ConfirmationTimeSet(transactionId, confirmationTime);\n }\n}\n", + "current/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol": + "/*\n\n Copyright 2018 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 solidity ^0.4.10;\n\nimport { MultiSigWalletWithTimeLock } from \"../MultiSigWalletWithTimeLock/MultiSigWalletWithTimeLock.sol\";\n\ncontract MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress is MultiSigWalletWithTimeLock {\n\n address public TOKEN_TRANSFER_PROXY_CONTRACT;\n\n modifier validRemoveAuthorizedAddressTx(uint transactionId) {\n Transaction storage tx = transactions[transactionId];\n require(tx.destination == TOKEN_TRANSFER_PROXY_CONTRACT);\n require(isFunctionRemoveAuthorizedAddress(tx.data));\n _;\n }\n\n /// @dev Contract constructor sets initial owners, required number of confirmations, time lock, and tokenTransferProxy address.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.\n /// @param _tokenTransferProxy Address of TokenTransferProxy contract.\n function MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress(\n address[] _owners,\n uint _required,\n uint _secondsTimeLocked,\n address _tokenTransferProxy)\n public\n MultiSigWalletWithTimeLock(_owners, _required, _secondsTimeLocked)\n {\n TOKEN_TRANSFER_PROXY_CONTRACT = _tokenTransferProxy;\n }\n\n /// @dev Allows execution of removeAuthorizedAddress without time lock.\n /// @param transactionId Transaction ID.\n function executeRemoveAuthorizedAddress(uint transactionId)\n public\n notExecuted(transactionId)\n fullyConfirmed(transactionId)\n validRemoveAuthorizedAddressTx(transactionId)\n {\n Transaction storage tx = transactions[transactionId];\n tx.executed = true;\n if (tx.destination.call.value(tx.value)(tx.data))\n Execution(transactionId);\n else {\n ExecutionFailure(transactionId);\n tx.executed = false;\n }\n }\n\n /// @dev Compares first 4 bytes of byte array to removeAuthorizedAddress function signature.\n /// @param data Transaction data.\n /// @return Successful if data is a call to removeAuthorizedAddress.\n function isFunctionRemoveAuthorizedAddress(bytes data)\n public\n constant\n returns (bool)\n {\n bytes4 removeAuthorizedAddressSignature = bytes4(sha3(\"removeAuthorizedAddress(address)\"));\n for (uint i = 0; i < 4; i++) {\n require(data[i] == removeAuthorizedAddressSignature[i]);\n }\n return true;\n }\n}\n" + }, + "sourceTreeHashHex": "0xdac022bb4f4cd50563fb21da8efb584e698d76b401d3c823cf757a1a2da3aea0", + "compiler": { + "name": "solc", + "version": "0.4.24", + "settings": { + "optimizer": { + "enabled": true, + "runs": 0 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap" + ] + } + } + } + }, + "networks": {} +} +>>>>>>> aa338761... updated migrations artifacts -- cgit v1.2.3 From 12e2bfc794831c0008bdbfc27dad9509f2578057 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 4 Jun 2018 18:14:44 -0700 Subject: Fixes after rebasing --- packages/contracts/test/asset_proxy/decoder.ts | 9 ++- packages/contracts/test/asset_proxy/proxies.ts | 4 +- packages/contracts/test/libraries/lib_bytes.ts | 1 + packages/order-utils/src/asset_proxy_utils.ts | 78 ++++++++++++++------------ packages/order-utils/src/order_state_utils.ts | 4 +- packages/types/src/index.ts | 7 ++- 6 files changed, 54 insertions(+), 49 deletions(-) diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 6336f69ae..f2668dfe6 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -1,5 +1,6 @@ import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; -import { generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { AssetData, AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import BN = require('bn.js'); @@ -10,10 +11,8 @@ import * as Web3 from 'web3'; import { TestAssetDataDecodersContract } from '../../src/contract_wrappers/generated/test_asset_data_decoders'; import { artifacts } from '../../src/utils/artifacts'; -import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; -import { AssetData, AssetProxyId, ERC20AssetData, ERC721AssetData } from '../../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); @@ -74,7 +73,7 @@ describe('TestAssetDataDecoders', () => { expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId); expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress); expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedAssetData.tokenId); - expect(decodedData).to.be.equal(expectedDecodedAssetData.data); + expect(decodedData).to.be.equal(expectedDecodedAssetData.receiverData); }); it('should correctly decode ERC721 asset data with receiver data', async () => { @@ -96,7 +95,7 @@ describe('TestAssetDataDecoders', () => { expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId); expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress); expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedAssetData.tokenId); - expect(decodedReceiverData).to.be.equal(expectedDecodedAssetData.data); + expect(decodedReceiverData).to.be.equal(expectedDecodedAssetData.receiverData); }); }); }); diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index 6dc652383..52a92718b 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -1,6 +1,6 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { assetProxyUtils } from '@0xproject/order-utils'; import { generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { assetProxyUtils } from '@0xproject/order-utils'; import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -18,13 +18,11 @@ import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c2 import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy'; import { artifacts } from '../../src/utils/artifacts'; import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions'; -import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC721Wrapper } from '../../src/utils/erc721_wrapper'; import { LogDecoder } from '../../src/utils/log_decoder'; -import { AssetProxyId } from '../../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 1a23483ba..9ae95d518 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -1,4 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { assetProxyUtils } from '@0xproject/order-utils'; import { generatePseudoRandomSalt } from '@0xproject/order-utils'; import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index a12be83a3..61a9b12e9 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -1,11 +1,11 @@ -import { AssetProxyId, ERC20ProxyData, ERC721ProxyData, ProxyData } from '@0xproject/types'; +import { AssetData, AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import BN = require('bn.js'); import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; -const ERC20_PROXY_METADATA_BYTE_LENGTH = 21; -const ERC721_PROXY_METADATA_BYTE_LENGTH = 53; +const ERC20_ASSET_DATA_BYTE_LENGTH = 21; +const ERC721_ASSET_DATA_BYTE_LENGTH = 53; export const assetProxyUtils = { encodeAssetProxyId(assetProxyId: AssetProxyId): Buffer { @@ -44,13 +44,13 @@ export const assetProxyUtils = { encodeERC20AssetData(tokenAddress: string): string { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC20); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); - const encodedMetadata = Buffer.concat([encodedAddress, encodedAssetProxyId]); - const encodedMetadataHex = ethUtil.bufferToHex(encodedMetadata); - return encodedMetadataHex; + const encodedAssetData = Buffer.concat([encodedAddress, encodedAssetProxyId]); + const encodedAssetDataHex = ethUtil.bufferToHex(encodedAssetData); + return encodedAssetDataHex; }, - decodeERC20ProxyData(proxyData: string): ERC20ProxyData { - const encodedProxyMetadata = ethUtil.toBuffer(proxyData); - if (encodedProxyMetadata.byteLength !== ERC20_PROXY_METADATA_BYTE_LENGTH) { + decodeERC20AssetData(proxyData: string): ERC20AssetData { + const encodedAssetData = ethUtil.toBuffer(proxyData); + if (encodedAssetData.byteLength !== ERC20_ASSET_DATA_BYTE_LENGTH) { throw new Error( `Could not decode ERC20 Proxy Data. Expected length of encoded data to be 21. Got ${ encodedAssetData.byteLength @@ -66,8 +66,8 @@ export const assetProxyUtils = { }), but got ${assetProxyId}`, ); } - const addressOffset = ERC20_PROXY_METADATA_BYTE_LENGTH - 1; - const encodedTokenAddress = encodedProxyMetadata.slice(0, addressOffset); + const addressOffset = ERC20_ASSET_DATA_BYTE_LENGTH - 1; + const encodedTokenAddress = encodedAssetData.slice(0, addressOffset); const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); const erc20AssetData = { assetProxyId, @@ -75,30 +75,36 @@ export const assetProxyUtils = { }; return erc20AssetData; }, - encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber, data?: string): string { + encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber, receiverData?: string): string { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC721); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); const encodedTokenId = assetProxyUtils.encodeUint256(tokenId); - let encodedMetadata = Buffer.concat([encodedAddress, encodedTokenId]); - if (!_.isUndefined(data)) { - const encodedData = ethUtil.toBuffer(data); - const dataLength = new BigNumber(encodedData.byteLength); - const encodedDataLength = assetProxyUtils.encodeUint256(dataLength); - encodedMetadata = Buffer.concat([encodedMetadata, encodedDataLength, encodedData]); + let encodedAssetData = Buffer.concat([encodedAddress, encodedTokenId]); + if (!_.isUndefined(receiverData)) { + const encodedReceiverData = ethUtil.toBuffer(receiverData); + const receiverDataLength = new BigNumber(encodedReceiverData.byteLength); + const encodedReceiverDataLength = assetProxyUtils.encodeUint256(receiverDataLength); + encodedAssetData = Buffer.concat([encodedAssetData, encodedReceiverDataLength, encodedReceiverData]); } - encodedMetadata = Buffer.concat([encodedMetadata, encodedAssetProxyId]); - const encodedMetadataHex = ethUtil.bufferToHex(encodedMetadata); - return encodedMetadataHex; + encodedAssetData = Buffer.concat([encodedAssetData, encodedAssetProxyId]); + const encodedAssetDataHex = ethUtil.bufferToHex(encodedAssetData); + return encodedAssetDataHex; }, decodeERC721AssetData(assetData: string): ERC721AssetData { const encodedAssetData = ethUtil.toBuffer(assetData); - if (encodedAssetData.byteLength < ERC721_PROXY_METADATA_BYTE_LENGTH) { + if (encodedAssetData.byteLength < ERC721_ASSET_DATA_BYTE_LENGTH) { throw new Error( `Could not decode ERC20 Proxy Data. Expected length of encoded data to be at least 53. Got ${ encodedAssetData.byteLength }`, ); } + const addressOffset = 0; + const tokenIdOffset = 20; + const receiverDataLengthOffset = 52; + const receiverDataOffset = 84; + const encodedTokenAddress = encodedAssetData.slice(addressOffset, tokenIdOffset); + const proxyIdOffset = encodedAssetData.byteLength - 1; const encodedAssetProxyId = encodedAssetData.slice(-1); const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); if (assetProxyId !== AssetProxyId.ERC721) { @@ -108,31 +114,31 @@ export const assetProxyUtils = { }), but got ${assetProxyId}`, ); } - const addressOffset = ERC20_PROXY_METADATA_BYTE_LENGTH - 1; - const encodedTokenAddress = encodedProxyMetadata.slice(0, addressOffset); const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); - const tokenIdOffset = ERC721_PROXY_METADATA_BYTE_LENGTH - 1; - const encodedTokenId = encodedProxyMetadata.slice(addressOffset, tokenIdOffset); + const encodedTokenId = encodedAssetData.slice(tokenIdOffset, receiverDataLengthOffset); const tokenId = assetProxyUtils.decodeUint256(encodedTokenId); const nullData = '0x'; - let data = nullData; - if (encodedAssetData.byteLength > 53) { - const encodedDataLength = encodedAssetData.slice(52, 84); - const dataLength = assetProxyUtils.decodeUint256(encodedDataLength); - const expectedDataLength = new BigNumber(encodedAssetData.byteLength - 85); - if (!dataLength.equals(expectedDataLength)) { + let receiverData = nullData; + if (encodedAssetData.byteLength > receiverDataLengthOffset + 1) { + const encodedReceiverDataLength = encodedAssetData.slice(receiverDataLengthOffset, receiverDataOffset); + const receiverDataLength = assetProxyUtils.decodeUint256(encodedReceiverDataLength); + const expectedReceiverDataLength = new BigNumber(encodedAssetData.byteLength - (receiverDataOffset + 1)); + if (!receiverDataLength.equals(expectedReceiverDataLength)) { throw new Error( - `Data length (${dataLength}) does not match actual length of data (${expectedDataLength})`, + `Data length (${receiverDataLength}) does not match actual length of data (${expectedReceiverDataLength})`, ); } - const encodedData = encodedAssetData.slice(84, expectedDataLength.toNumber() + 84); - data = ethUtil.bufferToHex(encodedData); + const encodedReceiverData = encodedAssetData.slice( + receiverDataOffset, + receiverDataOffset + receiverDataLength.toNumber(), + ); + receiverData = ethUtil.bufferToHex(encodedReceiverData); } const erc721AssetData: ERC721AssetData = { assetProxyId, tokenAddress, tokenId, - data, + receiverData, }; return erc721AssetData; }, diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index ca18097c9..12f5d8f7e 100644 --- a/packages/order-utils/src/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -111,8 +111,8 @@ export class OrderStateUtils { const transferrableMakerAssetAmount = BigNumber.min([makerProxyAllowance, makerBalance]); const transferrableFeeAssetAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]); - const zrxAssetData = assetProxyUtils.encodeERC20ProxyData(zrxTokenAddress); - const isMakerAssetZRX = signedOrder.makerAssetData === zrxAssetData; + const zrxAssetData = assetProxyUtils.encodeERC20AssetData(zrxTokenAddress); + const isMakerTokenZRX = signedOrder.makerAssetData === zrxAssetData; const remainingFillableCalculator = new RemainingFillableCalculator( signedOrder.makerFee, signedOrder.makerAssetAmount, diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 5ba66158e..0f7bb73be 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -156,18 +156,19 @@ export enum AssetProxyId { ERC721, } -export interface ERC20ProxyData { +export interface ERC20AssetData { assetProxyId: AssetProxyId; tokenAddress: string; } -export interface ERC721ProxyData { +export interface ERC721AssetData { assetProxyId: AssetProxyId; tokenAddress: string; tokenId: BigNumber; + receiverData: string; } -export interface ProxyData { +export interface AssetData { assetProxyId: AssetProxyId; tokenAddress?: string; data?: any; -- cgit v1.2.3 From a1b49d8389844c9b2d62ded91b76a23deb060ab6 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 4 Jun 2018 19:40:01 -0700 Subject: Fixed after rebase --- .../src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol | 4 ++-- .../src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol | 2 +- .../current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 4e9ae64f8..c8e8f4587 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -56,7 +56,7 @@ contract ERC20Proxy is // Data must be intended for this proxy. require( proxyId == PROXY_ID, - PROXY_ID_MISMATCH + ASSET_PROXY_ID_MISMATCH ); // Transfer tokens. @@ -93,7 +93,7 @@ contract ERC20Proxy is uint256 length = assetData.length; require( assetData.length == 21, - INVALID_ASSET_DATA_LENGTH + LENGTH_21_REQUIRED ); // Decode data diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index f6c3af104..7de7968cc 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -109,7 +109,7 @@ contract ERC721Proxy is uint256 length = assetData.length; require( assetData.length >= 53, - INVALID_ASSET_DATA_LENGTH + LENGTH_AT_LEAST_53_REQUIRED ); // Decode asset data. diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol index e0c7fc796..80180a0d9 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol @@ -29,9 +29,9 @@ contract LibAssetProxyErrors { /// AssetProxy errors /// string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // Proxy id in metadata does not match this proxy id. string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Transfer amount must equal 1. - string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed. + string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed. /// Length validation errors /// string constant LENGTH_21_REQUIRED = "LENGTH_21_REQUIRED"; // Byte array must have a length of 21. - string constant LENGTH_53_REQUIRED = "LENGTH_53_REQUIRED"; // Byte array must have a length of 53. + string constant LENGTH_AT_LEAST_53_REQUIRED = "LENGTH_AT_LEAST_53_REQUIRED"; // Byte array must have a length of at least 53. } -- cgit v1.2.3 From 774d831fae5809408f9ddfcf9393d579416b1bfb Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 4 Jun 2018 22:34:04 -0700 Subject: Style updates to ERC721 onReceiver --- packages/contracts/package.json | 2 +- .../contracts/current/protocol/AssetProxy/ERC20Proxy.sol | 1 - .../contracts/current/protocol/AssetProxy/ERC721Proxy.sol | 4 +--- .../src/contracts/current/utils/LibBytes/LibBytes.sol | 9 +++++---- packages/contracts/test/asset_proxy/decoder.ts | 14 ++++++++++++-- packages/contracts/test/asset_proxy/proxies.ts | 3 ++- packages/order-utils/src/asset_proxy_utils.ts | 10 ++++++---- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/packages/contracts/package.json b/packages/contracts/package.json index e436ae15e..b533a22ce 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -30,7 +30,7 @@ "test:circleci": "yarn test" }, "config": { - "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|DummyERC721Receiver|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetDataDecoders|TestAssetProxyDispatcher|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" + "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetDataDecoders|TestAssetProxyDispatcher|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json" }, "repository": { "type": "git", diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index c8e8f4587..50632400e 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -20,7 +20,6 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; -import "../../tokens/ERC20Token/IERC20Token.sol"; import "./MixinAssetProxy.sol"; import "./MixinAuthorizable.sol"; import "../../tokens/ERC20Token/IERC20Token.sol"; diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 7de7968cc..21e5518c6 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -33,8 +33,6 @@ contract ERC721Proxy is // Id of this proxy. uint8 constant PROXY_ID = 2; - string constant PROXY_ID_MISMATCH = "Proxy id in metadata does not match this proxy id."; - /// @dev Internal version of `transferFrom`. /// @param assetData Encoded byte array. /// @param from Address to transfer asset from. @@ -60,7 +58,7 @@ contract ERC721Proxy is // Data must be intended for this proxy. require( proxyId == PROXY_ID, - PROXY_ID_MISMATCH + ASSET_PROXY_ID_MISMATCH ); // There exists only 1 of each token. diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 5610c47b3..8f6647d20 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -332,7 +332,8 @@ contract LibBytes is internal pure { - // Read length of nested bytes + // Assert length of is valid, given + // length of input require( b.length >= index + 32 /* 32 bytes to store length */ + input.length, GTE_32_LENGTH_REQUIRED @@ -340,9 +341,9 @@ contract LibBytes is // Copy into memcpy( - getMemAddress(b) + index + 32, // +32 to skip length of - getMemAddress(input), // include length of byte array - input.length + 32 // +32 bytes to store length + getMemAddress(b) + 32 + index, // +32 to skip length of + getMemAddress(input), // includes length of + input.length + 32 // +32 bytes to store length ); } } diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index f2668dfe6..6a60c07bb 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -24,6 +24,12 @@ describe('TestAssetDataDecoders', () => { let testAssetProxyDecoder: TestAssetDataDecodersContract; let testAddress: string; + before(async () => { + await blockchainLifecycle.startAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); before(async () => { // Setup accounts & addresses const accounts = await web3Wrapper.getAvailableAddressesAsync(); @@ -78,8 +84,12 @@ describe('TestAssetDataDecoders', () => { it('should correctly decode ERC721 asset data with receiver data', async () => { const tokenId = generatePseudoRandomSalt(); - const receiverData = - ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt())) + 'FFFF'; + const receiverDataFirst32Bytes = ethUtil.bufferToHex( + assetProxyUtils.encodeUint256(generatePseudoRandomSalt()), + ); + const receiverDataExtraBytes = 'FFFF'; + // We add extra bytes to generate a value that doesn't fit perfectly into one word + const receiverData = receiverDataFirst32Bytes + receiverDataExtraBytes; const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId, receiverData); const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData); let decodedAssetProxyId: number; diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index 52a92718b..a7dc54efc 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -287,7 +287,7 @@ describe('Asset Transfer Proxies', () => { amount, { from: exchangeAddress }, ); - + await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); // Parse transaction logs const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address); const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash); @@ -319,6 +319,7 @@ describe('Asset Transfer Proxies', () => { amount, { from: exchangeAddress }, ); + await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); // Parse transaction logs const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address); const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash); diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index 61a9b12e9..c7b301c1a 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -119,10 +119,12 @@ export const assetProxyUtils = { const tokenId = assetProxyUtils.decodeUint256(encodedTokenId); const nullData = '0x'; let receiverData = nullData; - if (encodedAssetData.byteLength > receiverDataLengthOffset + 1) { + const lengthUpToReceiverDataLength = receiverDataLengthOffset + 1; + if (encodedAssetData.byteLength > lengthUpToReceiverDataLength) { const encodedReceiverDataLength = encodedAssetData.slice(receiverDataLengthOffset, receiverDataOffset); const receiverDataLength = assetProxyUtils.decodeUint256(encodedReceiverDataLength); - const expectedReceiverDataLength = new BigNumber(encodedAssetData.byteLength - (receiverDataOffset + 1)); + const lengthUpToReceiverData = receiverDataOffset + 1; + const expectedReceiverDataLength = new BigNumber(encodedAssetData.byteLength - lengthUpToReceiverData); if (!receiverDataLength.equals(expectedReceiverDataLength)) { throw new Error( `Data length (${receiverDataLength}) does not match actual length of data (${expectedReceiverDataLength})`, @@ -167,12 +169,12 @@ export const assetProxyUtils = { return generalizedERC20AssetData; case AssetProxyId.ERC721: const erc721AssetData = assetProxyUtils.decodeERC721AssetData(assetData); - const generaliedERC721AssetData = { + const generalizedERC721AssetData = { assetProxyId, tokenAddress: erc721AssetData.tokenAddress, data: erc721AssetData.tokenId, }; - return generaliedERC721AssetData; + return generalizedERC721AssetData; default: throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); } -- cgit v1.2.3 From b19276bb0f36059e67bb57b14e9f1e9e0efc17f2 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 5 Jun 2018 16:44:47 -0700 Subject: Fixed merge error when rebasing wrt length variable in asset data decoders --- .../src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol | 4 ++-- .../src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 50632400e..dd25bf41a 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -91,13 +91,13 @@ contract ERC20Proxy is // Validate encoded data length uint256 length = assetData.length; require( - assetData.length == 21, + length == 21, LENGTH_21_REQUIRED ); // Decode data token = readAddress(assetData, 0); - proxyId = uint8(assetData[length-1]); + proxyId = uint8(assetData[length - 1]); return (proxyId, token); } diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 21e5518c6..499d8d96e 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -106,14 +106,14 @@ contract ERC721Proxy is // Validate encoded data length uint256 length = assetData.length; require( - assetData.length >= 53, + length >= 53, LENGTH_AT_LEAST_53_REQUIRED ); // Decode asset data. token = readAddress(assetData, 0); tokenId = readUint256(assetData, 20); - if (assetData.length > 53) { + if (length > 53) { receiverData = readBytes(assetData, 52); } proxyId = uint8(assetData[length-1]); -- cgit v1.2.3 From 3c75d4f1ddf7ab5230fd00903110e2b51bf2598d Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 5 Jun 2018 17:07:45 -0700 Subject: Removed setting makerAssetData/takerAssetData from tests where values are same as defaultOrderParams. --- packages/contracts/test/exchange/match_orders.ts | 34 ------------------------ 1 file changed, 34 deletions(-) diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts index f34cbee1b..18a46187f 100644 --- a/packages/contracts/test/exchange/match_orders.ts +++ b/packages/contracts/test/exchange/match_orders.ts @@ -148,8 +148,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -182,8 +180,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -227,8 +223,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -261,8 +255,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -295,8 +287,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -364,8 +354,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -404,8 +392,6 @@ describe('matchOrders', () => { // branch in the contract twice for this test. const signedOrderLeft2 = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -437,8 +423,6 @@ describe('matchOrders', () => { const feeRecipientAddress = feeRecipientAddressLeft; const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress, @@ -465,8 +449,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -494,8 +476,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -523,8 +503,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -552,8 +530,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -581,8 +557,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: makerAddressLeft, @@ -609,8 +583,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -635,8 +607,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -661,8 +631,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, @@ -691,8 +659,6 @@ describe('matchOrders', () => { // Create orders to match const signedOrderLeft = orderFactoryLeft.newSignedOrder({ makerAddress: makerAddressLeft, - makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, -- cgit v1.2.3 From 37684c6af0d2962f7c7822dd14531787bd7b4212 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 5 Jun 2018 17:30:43 -0700 Subject: Fixed a styling throughout contracts. Moved closing parenthesis for long list of function parameters to next line. --- .../protocol/Exchange/MixinWrapperFunctions.sol | 27 ++++++++++++++-------- .../Exchange/interfaces/IAssetProxyDispatcher.sol | 3 ++- .../protocol/Exchange/interfaces/ITransactions.sol | 3 ++- .../Exchange/interfaces/IWrapperFunctions.sol | 27 ++++++++++++++-------- .../test/DummyERC20Token/DummyERC20Token.sol | 3 ++- .../DummyERC721Receiver/DummyERC721Receiver.sol | 3 ++- .../test/DummyERC721Token/DummyERC721Token.sol | 3 ++- .../current/test/TestLibBytes/TestLibBytes.sol | 24 ++++++++++++------- 8 files changed, 62 insertions(+), 31 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index f4822e814..e09f80bcc 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -40,7 +40,8 @@ contract MixinWrapperFunctions is function fillOrKillOrder( LibOrder.Order memory order, uint256 takerAssetFillAmount, - bytes memory signature) + bytes memory signature + ) public returns (FillResults memory fillResults) { @@ -65,7 +66,8 @@ contract MixinWrapperFunctions is function fillOrderNoThrow( LibOrder.Order memory order, uint256 takerAssetFillAmount, - bytes memory signature) + bytes memory signature + ) public returns (FillResults memory fillResults) { @@ -264,7 +266,8 @@ contract MixinWrapperFunctions is function batchFillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, - bytes[] memory signatures) + bytes[] memory signatures + ) public { for (uint256 i = 0; i < orders.length; i++) { @@ -283,7 +286,8 @@ contract MixinWrapperFunctions is function batchFillOrKillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, - bytes[] memory signatures) + bytes[] memory signatures + ) public { for (uint256 i = 0; i < orders.length; i++) { @@ -303,7 +307,8 @@ contract MixinWrapperFunctions is function batchFillOrdersNoThrow( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, - bytes[] memory signatures) + bytes[] memory signatures + ) public { for (uint256 i = 0; i < orders.length; i++) { @@ -323,7 +328,8 @@ contract MixinWrapperFunctions is function marketSellOrders( LibOrder.Order[] memory orders, uint256 takerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (FillResults memory totalFillResults) { @@ -366,7 +372,8 @@ contract MixinWrapperFunctions is function marketSellOrdersNoThrow( LibOrder.Order[] memory orders, uint256 takerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (FillResults memory totalFillResults) { @@ -408,7 +415,8 @@ contract MixinWrapperFunctions is function marketBuyOrders( LibOrder.Order[] memory orders, uint256 makerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (FillResults memory totalFillResults) { @@ -459,7 +467,8 @@ contract MixinWrapperFunctions is function marketBuyOrdersNoThrow( LibOrder.Order[] memory orders, uint256 makerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (FillResults memory totalFillResults) { diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol index 3ce5ef157..2c331dc34 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol @@ -28,7 +28,8 @@ contract IAssetProxyDispatcher { function registerAssetProxy( uint8 assetProxyId, address newAssetProxy, - address oldAssetProxy) + address oldAssetProxy + ) external; /// @dev Gets an asset proxy. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol index d973bf001..2f9a5bc7c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol @@ -28,6 +28,7 @@ contract ITransactions { uint256 salt, address signer, bytes data, - bytes signature) + bytes signature + ) external; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol index 8682b394a..acd4f359c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol @@ -33,7 +33,8 @@ contract IWrapperFunctions is function fillOrKillOrder( LibOrder.Order memory order, uint256 takerAssetFillAmount, - bytes memory signature) + bytes memory signature + ) public returns (LibFillResults.FillResults memory fillResults); @@ -46,7 +47,8 @@ contract IWrapperFunctions is function fillOrderNoThrow( LibOrder.Order memory order, uint256 takerAssetFillAmount, - bytes memory signature) + bytes memory signature + ) public returns (LibFillResults.FillResults memory fillResults); @@ -57,7 +59,8 @@ contract IWrapperFunctions is function batchFillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, - bytes[] memory signatures) + bytes[] memory signatures + ) public; /// @dev Synchronously executes multiple calls of fillOrKill. @@ -67,7 +70,8 @@ contract IWrapperFunctions is function batchFillOrKillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, - bytes[] memory signatures) + bytes[] memory signatures + ) public; /// @dev Fills an order with specified parameters and ECDSA signature. @@ -78,7 +82,8 @@ contract IWrapperFunctions is function batchFillOrdersNoThrow( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, - bytes[] memory signatures) + bytes[] memory signatures + ) public; /// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker. @@ -89,7 +94,8 @@ contract IWrapperFunctions is function marketSellOrders( LibOrder.Order[] memory orders, uint256 takerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (LibFillResults.FillResults memory totalFillResults); @@ -102,7 +108,8 @@ contract IWrapperFunctions is function marketSellOrdersNoThrow( LibOrder.Order[] memory orders, uint256 takerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (LibFillResults.FillResults memory totalFillResults); @@ -114,7 +121,8 @@ contract IWrapperFunctions is function marketBuyOrders( LibOrder.Order[] memory orders, uint256 makerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (LibFillResults.FillResults memory totalFillResults); @@ -127,7 +135,8 @@ contract IWrapperFunctions is function marketBuyOrdersNoThrow( LibOrder.Order[] memory orders, uint256 makerAssetFillAmount, - bytes[] memory signatures) + bytes[] memory signatures + ) public returns (LibFillResults.FillResults memory totalFillResults); diff --git a/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol b/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol index 0c7b18c0c..b2fe2df06 100644 --- a/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol +++ b/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol @@ -31,7 +31,8 @@ contract DummyERC20Token is Mintable, Ownable { string _name, string _symbol, uint256 _decimals, - uint256 _totalSupply) + uint256 _totalSupply + ) public { name = _name; diff --git a/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol b/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol index 1596f3357..c584d0b54 100644 --- a/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol +++ b/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol @@ -52,7 +52,8 @@ contract DummyERC721Receiver is function onERC721Received( address _from, uint256 _tokenId, - bytes _data) + bytes _data + ) public returns (bytes4) { diff --git a/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol index 369a2950d..5503eb2f2 100644 --- a/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol +++ b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol @@ -34,7 +34,8 @@ contract DummyERC721Token is */ constructor ( string name, - string symbol) + string symbol + ) public ERC721Token(name, symbol) {} diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index f009a6a71..22c84504c 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -68,7 +68,8 @@ contract TestLibBytes is /// @return address from byte array. function publicReadAddress( bytes memory b, - uint256 index) + uint256 index + ) public pure returns (address result) @@ -84,7 +85,8 @@ contract TestLibBytes is function publicWriteAddress( bytes memory b, uint256 index, - address input) + address input + ) public pure returns (bytes memory) @@ -99,7 +101,8 @@ contract TestLibBytes is /// @return bytes32 value from byte array. function publicReadBytes32( bytes memory b, - uint256 index) + uint256 index + ) public pure returns (bytes32 result) @@ -115,7 +118,8 @@ contract TestLibBytes is function publicWriteBytes32( bytes memory b, uint256 index, - bytes32 input) + bytes32 input + ) public pure returns (bytes memory) @@ -130,7 +134,8 @@ contract TestLibBytes is /// @return uint256 value from byte array. function publicReadUint256( bytes memory b, - uint256 index) + uint256 index + ) public pure returns (uint256 result) @@ -146,7 +151,8 @@ contract TestLibBytes is function publicWriteUint256( bytes memory b, uint256 index, - uint256 input) + uint256 input + ) public pure returns (bytes memory) @@ -173,7 +179,8 @@ contract TestLibBytes is /// @return result Nested bytes. function publicReadBytes( bytes memory b, - uint256 index) + uint256 index + ) public pure returns (bytes memory result) @@ -190,7 +197,8 @@ contract TestLibBytes is function publicWriteBytes( bytes memory b, uint256 index, - bytes memory input) + bytes memory input + ) public pure returns (bytes memory) -- cgit v1.2.3 From db086de84ae7a238b91b5ce79fcc1a8e4c830ac5 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 6 Jun 2018 17:14:13 -0700 Subject: Union types for generalized decodeAssetData --- packages/contracts/test/asset_proxy/decoder.ts | 4 ++-- packages/order-utils/src/asset_proxy_utils.ts | 17 ++++------------- packages/types/src/index.ts | 6 ------ 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 6a60c07bb..2577dbba5 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -1,6 +1,6 @@ import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; -import { AssetData, AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; +import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import BN = require('bn.js'); @@ -19,7 +19,7 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -describe('TestAssetDataDecoders', () => { +describe.only('TestAssetDataDecoders', () => { let owner: string; let testAssetProxyDecoder: TestAssetDataDecodersContract; let testAddress: string; diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index c7b301c1a..1d34172c7 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -1,4 +1,4 @@ -import { AssetData, AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; +import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import BN = require('bn.js'); import ethUtil = require('ethereumjs-util'); @@ -157,24 +157,15 @@ export const assetProxyUtils = { const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); return assetProxyId; }, - decodeAssetData(assetData: string): AssetData { + decodeAssetData(assetData: string): ERC20AssetData | ERC721AssetData { const assetProxyId = assetProxyUtils.decodeAssetDataId(assetData); switch (assetProxyId) { case AssetProxyId.ERC20: const erc20AssetData = assetProxyUtils.decodeERC20AssetData(assetData); - const generalizedERC20AssetData = { - assetProxyId, - tokenAddress: erc20AssetData.tokenAddress, - }; - return generalizedERC20AssetData; + return erc20AssetData; case AssetProxyId.ERC721: const erc721AssetData = assetProxyUtils.decodeERC721AssetData(assetData); - const generalizedERC721AssetData = { - assetProxyId, - tokenAddress: erc721AssetData.tokenAddress, - data: erc721AssetData.tokenId, - }; - return generalizedERC721AssetData; + return erc721AssetData; default: throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 0f7bb73be..a5da947e1 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -167,9 +167,3 @@ export interface ERC721AssetData { tokenId: BigNumber; receiverData: string; } - -export interface AssetData { - assetProxyId: AssetProxyId; - tokenAddress?: string; - data?: any; -} -- cgit v1.2.3 From f457a56d4a0a4e5a5b5b11289f65df64cf2c7f1f Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Jun 2018 11:11:40 -0700 Subject: Style updates to contracts --- .../current/protocol/AssetProxy/ERC721Proxy.sol | 2 +- .../contracts/current/utils/LibBytes/LibBytes.sol | 28 +++++++++++----------- packages/contracts/src/utils/artifacts.ts | 2 +- packages/contracts/test/asset_proxy/decoder.ts | 6 ++--- packages/contracts/test/asset_proxy/proxies.ts | 5 +--- packages/contracts/test/libraries/lib_bytes.ts | 3 +-- packages/order-utils/src/asset_proxy_utils.ts | 5 ++-- 7 files changed, 23 insertions(+), 28 deletions(-) diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 499d8d96e..25136133d 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -116,7 +116,7 @@ contract ERC721Proxy is if (length > 53) { receiverData = readBytes(assetData, 52); } - proxyId = uint8(assetData[length-1]); + proxyId = uint8(assetData[length - 1]); return ( proxyId, diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 8f6647d20..282455ea0 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -25,11 +25,11 @@ contract LibBytes is { // Revert reasons - string constant GT_ZERO_LENGTH_REQUIRED = "Length must be greater than 0."; - string constant GTE_4_LENGTH_REQUIRED = "Length must be greater than or equal to 4."; - string constant GTE_20_LENGTH_REQUIRED = "Length must be greater than or equal to 20."; - string constant GTE_32_LENGTH_REQUIRED = "Length must be greater than or equal to 32."; - string constant INDEX_OUT_OF_BOUNDS = "Specified array index is out of bounds."; + string constant GREATER_THAN_ZERO_LENGTH_REQUIRED = "GREATER_THAN_ZERO_LENGTH_REQUIRED"; + string constant GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED = "GREATER_THAN_4_LENGTH_REQUIRED"; + string constant GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED"; + string constant GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED"; + string constant GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED"; /// @dev Pops the last byte off of a byte array by modifying its length. /// @param b Byte array that will be modified. @@ -41,7 +41,7 @@ contract LibBytes is { require( b.length > 0, - GT_ZERO_LENGTH_REQUIRED + GREATER_THAN_ZERO_LENGTH_REQUIRED ); // Store last byte. @@ -65,7 +65,7 @@ contract LibBytes is { require( b.length >= 20, - GTE_20_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED ); // Store last 20 bytes. @@ -128,7 +128,7 @@ contract LibBytes is { require( b.length >= index + 20, // 20 is length of address - GTE_20_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED ); // Add offset to index: @@ -160,7 +160,7 @@ contract LibBytes is { require( b.length >= index + 20, // 20 is length of address - GTE_20_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED ); // Add offset to index: @@ -199,7 +199,7 @@ contract LibBytes is { require( b.length >= index + 32, - GTE_32_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED ); // Arrays are prefixed by a 256 bit length parameter @@ -226,7 +226,7 @@ contract LibBytes is { require( b.length >= index + 32, - GTE_32_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED ); // Arrays are prefixed by a 256 bit length parameter @@ -278,7 +278,7 @@ contract LibBytes is { require( b.length >= 4, - GTE_4_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED ); assembly { result := mload(add(b, 32)) @@ -306,7 +306,7 @@ contract LibBytes is // length of nested bytes require( b.length >= index + nestedBytesLength, - GTE_32_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED ); // Allocate memory and copy value to result @@ -336,7 +336,7 @@ contract LibBytes is // length of input require( b.length >= index + 32 /* 32 bytes to store length */ + input.length, - GTE_32_LENGTH_REQUIRED + GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED ); // Copy into diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index 42de7c921..bf7221d6d 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -10,8 +10,8 @@ import * as Exchange from '../artifacts/Exchange.json'; import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json'; import * as MultiSigWallet from '../artifacts/MultiSigWallet.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json'; -import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json'; import * as TestAssetDataDecoders from '../artifacts/TestAssetDataDecoders.json'; +import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json'; import * as TestLibBytes from '../artifacts/TestLibBytes.json'; import * as TestLibMem from '../artifacts/TestLibMem.json'; import * as TestLibs from '../artifacts/TestLibs.json'; diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 2577dbba5..16486f4fd 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -1,11 +1,9 @@ -import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import BN = require('bn.js'); import * as chai from 'chai'; -import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import ethUtil = require('ethereumjs-util'); import * as Web3 from 'web3'; @@ -19,7 +17,7 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -describe.only('TestAssetDataDecoders', () => { +describe('TestAssetDataDecoders', () => { let owner: string; let testAssetProxyDecoder: TestAssetDataDecodersContract; let testAddress: string; diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index a7dc54efc..7687d4648 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -1,6 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { generatePseudoRandomSalt } from '@0xproject/order-utils'; -import { assetProxyUtils } from '@0xproject/order-utils'; +import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -30,8 +29,6 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('Asset Transfer Proxies', () => { - const nullDataHex = '0x'; - let owner: string; let notAuthorized: string; let exchangeAddress: string; diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 9ae95d518..5830c5753 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -1,6 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { assetProxyUtils } from '@0xproject/order-utils'; -import { generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import BN = require('bn.js'); diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index 1d34172c7..ed8832b18 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -4,6 +4,8 @@ import BN = require('bn.js'); import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; +import { constants } from '../../src/utils/constants'; + const ERC20_ASSET_DATA_BYTE_LENGTH = 21; const ERC721_ASSET_DATA_BYTE_LENGTH = 53; @@ -117,8 +119,7 @@ export const assetProxyUtils = { const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); const encodedTokenId = encodedAssetData.slice(tokenIdOffset, receiverDataLengthOffset); const tokenId = assetProxyUtils.decodeUint256(encodedTokenId); - const nullData = '0x'; - let receiverData = nullData; + let receiverData = constants.NULL_BYTE; const lengthUpToReceiverDataLength = receiverDataLengthOffset + 1; if (encodedAssetData.byteLength > lengthUpToReceiverDataLength) { const encodedReceiverDataLength = encodedAssetData.slice(receiverDataLengthOffset, receiverDataOffset); -- cgit v1.2.3 From f0200ab69722a7913671f3e59ab650da1e77d6ef Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Jun 2018 11:21:31 -0700 Subject: Moved some constants to global scope in assetProxyUtils --- packages/order-utils/src/asset_proxy_utils.ts | 44 ++++++++++++++++----------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index ed8832b18..e2b377899 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -1,13 +1,15 @@ import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { BigNumber, NULL_BYTES } from '@0xproject/utils'; import BN = require('bn.js'); import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; -import { constants } from '../../src/utils/constants'; - const ERC20_ASSET_DATA_BYTE_LENGTH = 21; const ERC721_ASSET_DATA_BYTE_LENGTH = 53; +const ASSET_DATA_ADDRESS_OFFSET = 0; +const ERC721_ASSET_DATA_TOKEN_ID_OFFSET = 20; +const ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET = 52; +const ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET = 84; export const assetProxyUtils = { encodeAssetProxyId(assetProxyId: AssetProxyId): Buffer { @@ -59,7 +61,8 @@ export const assetProxyUtils = { }`, ); } - const encodedAssetProxyId = encodedAssetData.slice(-1); + const assetProxyIdOffset = encodedAssetData.byteLength - 1; + const encodedAssetProxyId = encodedAssetData.slice(assetProxyIdOffset); const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); if (assetProxyId !== AssetProxyId.ERC20) { throw new Error( @@ -68,8 +71,7 @@ export const assetProxyUtils = { }), but got ${assetProxyId}`, ); } - const addressOffset = ERC20_ASSET_DATA_BYTE_LENGTH - 1; - const encodedTokenAddress = encodedAssetData.slice(0, addressOffset); + const encodedTokenAddress = encodedAssetData.slice(ASSET_DATA_ADDRESS_OFFSET, assetProxyIdOffset); const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); const erc20AssetData = { assetProxyId, @@ -101,11 +103,11 @@ export const assetProxyUtils = { }`, ); } - const addressOffset = 0; - const tokenIdOffset = 20; - const receiverDataLengthOffset = 52; - const receiverDataOffset = 84; - const encodedTokenAddress = encodedAssetData.slice(addressOffset, tokenIdOffset); + + const encodedTokenAddress = encodedAssetData.slice( + ASSET_DATA_ADDRESS_OFFSET, + ERC721_ASSET_DATA_TOKEN_ID_OFFSET, + ); const proxyIdOffset = encodedAssetData.byteLength - 1; const encodedAssetProxyId = encodedAssetData.slice(-1); const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); @@ -117,14 +119,20 @@ export const assetProxyUtils = { ); } const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); - const encodedTokenId = encodedAssetData.slice(tokenIdOffset, receiverDataLengthOffset); + const encodedTokenId = encodedAssetData.slice( + ERC721_ASSET_DATA_TOKEN_ID_OFFSET, + ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET, + ); const tokenId = assetProxyUtils.decodeUint256(encodedTokenId); - let receiverData = constants.NULL_BYTE; - const lengthUpToReceiverDataLength = receiverDataLengthOffset + 1; + let receiverData = NULL_BYTES; + const lengthUpToReceiverDataLength = ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET + 1; if (encodedAssetData.byteLength > lengthUpToReceiverDataLength) { - const encodedReceiverDataLength = encodedAssetData.slice(receiverDataLengthOffset, receiverDataOffset); + const encodedReceiverDataLength = encodedAssetData.slice( + ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET, + ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET, + ); const receiverDataLength = assetProxyUtils.decodeUint256(encodedReceiverDataLength); - const lengthUpToReceiverData = receiverDataOffset + 1; + const lengthUpToReceiverData = ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET + 1; const expectedReceiverDataLength = new BigNumber(encodedAssetData.byteLength - lengthUpToReceiverData); if (!receiverDataLength.equals(expectedReceiverDataLength)) { throw new Error( @@ -132,8 +140,8 @@ export const assetProxyUtils = { ); } const encodedReceiverData = encodedAssetData.slice( - receiverDataOffset, - receiverDataOffset + receiverDataLength.toNumber(), + ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET, + ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET + receiverDataLength.toNumber(), ); receiverData = ethUtil.bufferToHex(encodedReceiverData); } -- cgit v1.2.3 From 5bb7219f4b8d5ce22169d5139bd1c07d7b2fcafd Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Jun 2018 11:43:17 -0700 Subject: Camelcase in memCopy --- .../current/test/TestLibMem/TestLibMem.sol | 8 +++--- .../contracts/current/utils/LibBytes/LibBytes.sol | 4 +-- .../src/contracts/current/utils/LibMem/LibMem.sol | 32 +++++++++++----------- packages/contracts/test/libraries/lib_mem.ts | 2 +- packages/order-utils/src/asset_proxy_utils.ts | 4 +-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol index 076bee24c..b7e2e06b8 100644 --- a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol +++ b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol @@ -25,11 +25,11 @@ contract TestLibMem is { /// @dev Copies a block of memory from one location to another. - /// @param mem Memory contents we want to apply memcpy to + /// @param mem Memory contents we want to apply memCopy to /// @param dest Destination offset into . /// @param source Source offset into . /// @param length Length of bytes to copy from to - /// @return mem Memory contents after calling memcpy. + /// @return mem Memory contents after calling memCopy. function testMemcpy( bytes mem, uint256 dest, @@ -47,8 +47,8 @@ contract TestLibMem is // Get pointer to memory contents uint256 offset = getMemAddress(mem) + 32; - // Execute memcpy adjusted for memory array location - memcpy(offset + dest, offset + source, length); + // Execute memCopy adjusted for memory array location + memCopy(offset + dest, offset + source, length); // Return modified memory contents return mem; diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 282455ea0..4f9e2f152 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -311,7 +311,7 @@ contract LibBytes is // Allocate memory and copy value to result result = new bytes(nestedBytesLength); - memcpy( + memCopy( getMemAddress(result) + 32, // +32 skips array length getMemAddress(b) + index + 32, nestedBytesLength @@ -340,7 +340,7 @@ contract LibBytes is ); // Copy into - memcpy( + memCopy( getMemAddress(b) + 32 + index, // +32 to skip length of getMemAddress(input), // includes length of input.length + 32 // +32 bytes to store length diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol index 960850725..6afb9973a 100644 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -39,7 +39,7 @@ contract LibMem /// @param dest memory address to copy bytes to. /// @param source memory address to copy bytes from. /// @param length number of bytes to copy. - function memcpy( + function memCopy( uint256 dest, uint256 source, uint256 length @@ -81,42 +81,42 @@ contract LibMem if (source > dest) { assembly { // Record the total number of full words to copy - let nwords := div(length, 32) + let nWords := div(length, 32) - // We subtract 32 from `send` and `dend` because it + // We subtract 32 from `sEnd` and `dEnd` because it // is easier to compare with in the loop, and these // are also the addresses we need for copying the // last bytes. length := sub(length, 32) - let send := add(source, length) - let dend := add(dest, length) + let sEnd := add(source, length) + let dEnd := add(dest, length) // Remember the last 32 bytes of source // This needs to be done here and not after the loop // because we may have overwritten the last bytes in // source already due to overlap. - let last := mload(send) + let last := mload(sEnd) // Copy whole words front to back - for {let i := 0} lt(i, nwords) {i := add(i, 1)} { + for {let i := 0} lt(i, nWords) {i := add(i, 1)} { mstore(dest, mload(source)) source := add(source, 32) dest := add(dest, 32) } // Write the last 32 bytes - mstore(dend, last) + mstore(dEnd, last) } } else { assembly { // Record the total number of full words to copy - let nwords := div(length, 32) + let nWords := div(length, 32) - // We subtract 32 from `send` and `dend` because those + // We subtract 32 from `sEnd` and `dEnd` because those // are the starting points when copying a word at the end. length := sub(length, 32) - let send := add(source, length) - let dend := add(dest, length) + let sEnd := add(source, length) + let dEnd := add(dest, length) // Remember the first 32 bytes of source // This needs to be done here and not after the loop @@ -125,10 +125,10 @@ contract LibMem let first := mload(source) // Copy whole words back to front - for {let i := 0} lt(i, nwords) {i := add(i, 1)} { - mstore(dend, mload(send)) - send := sub(send, 32) - dend := sub(dend, 32) + for {let i := 0} lt(i, nWords) {i := add(i, 1)} { + mstore(dEnd, mload(sEnd)) + sEnd := sub(sEnd, 32) + dEnd := sub(dEnd, 32) } // Write the first 32 bytes diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index efe719255..6291d3d08 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -27,7 +27,7 @@ describe('LibMem', () => { testLibMem = await TestLibMemContract.deployFrom0xArtifactAsync(artifacts.TestLibMem, provider, txDefaults); }); - describe('memcpy', () => { + describe('memCopy', () => { // Create memory 0x000102...FF const memSize = 256; const memory = new Uint8Array(memSize).map((_, i) => i); diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index e2b377899..ee5fff1d2 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -5,7 +5,7 @@ import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; const ERC20_ASSET_DATA_BYTE_LENGTH = 21; -const ERC721_ASSET_DATA_BYTE_LENGTH = 53; +const ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH = 53; const ASSET_DATA_ADDRESS_OFFSET = 0; const ERC721_ASSET_DATA_TOKEN_ID_OFFSET = 20; const ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET = 52; @@ -96,7 +96,7 @@ export const assetProxyUtils = { }, decodeERC721AssetData(assetData: string): ERC721AssetData { const encodedAssetData = ethUtil.toBuffer(assetData); - if (encodedAssetData.byteLength < ERC721_ASSET_DATA_BYTE_LENGTH) { + if (encodedAssetData.byteLength < ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH) { throw new Error( `Could not decode ERC20 Proxy Data. Expected length of encoded data to be at least 53. Got ${ encodedAssetData.byteLength -- cgit v1.2.3 From 8ace41d14473462dda297d4dd970b095e747e2b0 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Jun 2018 13:46:54 -0700 Subject: Minor fixes after rebase --- packages/contracts/test/asset_proxy/proxies.ts | 20 +- packages/fill-scenarios/src/index.ts | 8 +- ...tWithTimeLockExceptRemoveAuthorizedAddress.json | 736 +-------------------- 3 files changed, 11 insertions(+), 753 deletions(-) diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index 7687d4648..0548a2aac 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -226,13 +226,9 @@ describe('Asset Transfer Proxies', () => { const amounts = _.times(numTransfers, () => amount); return expectRevertOrAlwaysFailingTransactionAsync( - erc20Proxy.batchTransferFrom.sendTransactionAsync( - encodedAssetData, - fromAddresses, - toAddresses, - amounts, - { from: notAuthorized }, - ), + erc20Proxy.batchTransferFrom.sendTransactionAsync(assetData, fromAddresses, toAddresses, amounts, { + from: notAuthorized, + }), ); }); }); @@ -477,13 +473,9 @@ describe('Asset Transfer Proxies', () => { const amounts = _.times(numTransfers, () => new BigNumber(1)); return expectRevertOrAlwaysFailingTransactionAsync( - erc721Proxy.batchTransferFrom.sendTransactionAsync( - encodedAssetData, - fromAddresses, - toAddresses, - amounts, - { from: notAuthorized }, - ), + erc721Proxy.batchTransferFrom.sendTransactionAsync(assetData, fromAddresses, toAddresses, amounts, { + from: notAuthorized, + }), ); }); }); diff --git a/packages/fill-scenarios/src/index.ts b/packages/fill-scenarios/src/index.ts index dc877a0fd..038826af2 100644 --- a/packages/fill-scenarios/src/index.ts +++ b/packages/fill-scenarios/src/index.ts @@ -169,10 +169,10 @@ export class FillScenarios { feeRecepientAddress: string, expirationTimeSeconds?: BigNumber, ): Promise { - const makerERC20ProxyData = assetProxyUtils.decodeERC20ProxyData(makerAssetData); - const makerTokenAddress = makerERC20ProxyData.tokenAddress; - const takerERC20ProxyData = assetProxyUtils.decodeERC20ProxyData(takerAssetData); - const takerTokenAddress = takerERC20ProxyData.tokenAddress; + const makerERC20AssetData = assetProxyUtils.decodeERC20AssetData(makerAssetData); + const makerTokenAddress = makerERC20AssetData.tokenAddress; + const takerERC20AssetData = assetProxyUtils.decodeERC20AssetData(takerAssetData); + const takerTokenAddress = takerERC20AssetData.tokenAddress; await Promise.all([ this._increaseERC20BalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount), this._increaseERC20BalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount), diff --git a/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json b/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json index 53099f1e4..b3d1eca61 100644 --- a/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json +++ b/packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json @@ -1,5 +1,4 @@ { -<<<<<<< HEAD "schemaVersion": "2.0.0", "contractName": "MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress", "compilerOutput": { @@ -721,737 +720,4 @@ } }, "networks": {} -} -======= - "schemaVersion": "2.0.0", - "contractName": "MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress", - "compilerOutput": { - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "owner", - "type": "address" - } - ], - "name": "removeOwner", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "revokeConfirmation", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "address" - } - ], - "name": "confirmations", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "secondsTimeLocked", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "pending", - "type": "bool" - }, - { - "name": "executed", - "type": "bool" - } - ], - "name": "getTransactionCount", - "outputs": [ - { - "name": "count", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "data", - "type": "bytes" - } - ], - "name": "isFunctionRemoveAuthorizedAddress", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "executeRemoveAuthorizedAddress", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "owner", - "type": "address" - } - ], - "name": "addOwner", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "isConfirmed", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_secondsTimeLocked", - "type": "uint256" - } - ], - "name": "changeTimeLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "getConfirmationCount", - "outputs": [ - { - "name": "count", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "transactions", - "outputs": [ - { - "name": "destination", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "executed", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getOwners", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "from", - "type": "uint256" - }, - { - "name": "to", - "type": "uint256" - }, - { - "name": "pending", - "type": "bool" - }, - { - "name": "executed", - "type": "bool" - } - ], - "name": "getTransactionIds", - "outputs": [ - { - "name": "_transactionIds", - "type": "uint256[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_TRANSFER_PROXY_CONTRACT", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "getConfirmations", - "outputs": [ - { - "name": "_confirmations", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transactionCount", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_required", - "type": "uint256" - } - ], - "name": "changeRequirement", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "confirmTransaction", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "destination", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - } - ], - "name": "submitTransaction", - "outputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "confirmationTimes", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_OWNER_COUNT", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "required", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "owner", - "type": "address" - }, - { - "name": "newOwner", - "type": "address" - } - ], - "name": "replaceOwner", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "executeTransaction", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_owners", - "type": "address[]" - }, - { - "name": "_required", - "type": "uint256" - }, - { - "name": "_secondsTimeLocked", - "type": "uint256" - }, - { - "name": "_tokenTransferProxy", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - }, - { - "indexed": false, - "name": "confirmationTime", - "type": "uint256" - } - ], - "name": "ConfirmationTimeSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "secondsTimeLocked", - "type": "uint256" - } - ], - "name": "TimeLockChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Confirmation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Revocation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Submission", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Execution", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "ExecutionFailure", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "OwnerAddition", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "OwnerRemoval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "required", - "type": "uint256" - } - ], - "name": "RequirementChange", - "type": "event" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": - "0x60806040523480156200001157600080fd5b5060405162001b2738038062001b278339810160409081528151602083015191830151606084015191909301805190939190849084908490839083906000908260328211806200006057508181115b806200006a575080155b8062000074575081155b156200007f57600080fd5b600092505b84518310156200015357600260008685815181101515620000a157fe5b6020908102909101810151600160a060020a031682528101919091526040016000205460ff1680620000f457508483815181101515620000dd57fe5b90602001906020020151600160a060020a03166000145b15620000ff57600080fd5b60016002600087868151811015156200011457fe5b602090810291909101810151600160a060020a03168252810191909152604001600020805460ff19169115159190911790556001929092019162000084565b845162000168906003906020880190620001a2565b5050506004919091555050600655505060088054600160a060020a031916600160a060020a03929092169190911790555062000236915050565b828054828255906000526020600020908101928215620001fa579160200282015b82811115620001fa5782518254600160a060020a031916600160a060020a03909116178255602090920191600190910190620001c3565b50620002089291506200020c565b5090565b6200023391905b8082111562000208578054600160a060020a031916815560010162000213565b90565b6118e180620002466000396000f3006080604052600436106101455763ffffffff60e060020a600035041663025e7c278114610187578063173825d9146101bb57806320ea8d86146101dc5780632f54bf6e146101f45780633411c81c1461022957806337bd78a01461024d5780635474152514610274578063553a48fd146102935780635711b311146102ec5780637065cb4814610304578063784547a7146103255780637ad28c511461033d5780638b51d13f146103555780639ace38c21461036d578063a0e67e2b14610428578063a8abe69a1461048d578063add1cbc5146104b2578063b5dc40c3146104c7578063b77bf600146104df578063ba51a6df146104f4578063c01a8c841461050c578063c642747414610524578063d38f2d821461058d578063d74f8edd146105a5578063dc8452cd146105ba578063e20056e6146105cf578063ee22610b146105f6575b60003411156101855760408051348152905133917fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c919081900360200190a25b005b34801561019357600080fd5b5061019f60043561060e565b60408051600160a060020a039092168252519081900360200190f35b3480156101c757600080fd5b50610185600160a060020a0360043516610636565b3480156101e857600080fd5b5061018560043561079b565b34801561020057600080fd5b50610215600160a060020a036004351661086a565b604080519115158252519081900360200190f35b34801561023557600080fd5b50610215600435600160a060020a036024351661087f565b34801561025957600080fd5b5061026261089f565b60408051918252519081900360200190f35b34801561028057600080fd5b50610262600435151560243515156108a5565b34801561029f57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102159436949293602493928401919081908401838280828437509497506109119650505050505050565b3480156102f857600080fd5b506101856004356109b4565b34801561031057600080fd5b50610185600160a060020a0360043516610bc7565b34801561033157600080fd5b50610215600435610cc5565b34801561034957600080fd5b50610185600435610d42565b34801561036157600080fd5b50610262600435610d89565b34801561037957600080fd5b50610385600435610df8565b6040518085600160a060020a0316600160a060020a031681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156103ea5781810151838201526020016103d2565b50505050905090810190601f1680156104175780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561043457600080fd5b5061043d610eb6565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610479578181015183820152602001610461565b505050509050019250505060405180910390f35b34801561049957600080fd5b5061043d60043560243560443515156064351515610f19565b3480156104be57600080fd5b5061019f611052565b3480156104d357600080fd5b5061043d600435611061565b3480156104eb57600080fd5b506102626111da565b34801561050057600080fd5b506101856004356111e0565b34801561051857600080fd5b50610185600435611257565b34801561053057600080fd5b50604080516020600460443581810135601f8101849004840285018401909552848452610262948235600160a060020a031694602480359536959460649492019190819084018382808284375094975061133e9650505050505050565b34801561059957600080fd5b5061026260043561135d565b3480156105b157600080fd5b5061026261136f565b3480156105c657600080fd5b50610262611374565b3480156105db57600080fd5b50610185600160a060020a036004358116906024351661137a565b34801561060257600080fd5b506101856004356114e0565b600380548290811061061c57fe5b600091825260209091200154600160a060020a0316905081565b600033301461064457600080fd5b600160a060020a038216600090815260026020526040902054829060ff16151561066d57600080fd5b600160a060020a0383166000908152600260205260408120805460ff1916905591505b600354600019018210156107485782600160a060020a03166003838154811015156106b757fe5b600091825260209091200154600160a060020a0316141561073d576003805460001981019081106106e457fe5b60009182526020909120015460038054600160a060020a03909216918490811061070a57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a03160217905550610748565b600190910190610690565b60038054600019019061075b9082611774565b50600354600454111561077457600354610774906111e0565b604051600160a060020a0384169060008051602061189683398151915290600090a2505050565b3360008181526002602052604090205460ff1615156107b957600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1615156107e557600080fd5b600084815260208190526040902060030154849060ff161561080657600080fd5b8461081081610cc5565b1561081a57600080fd5b6000868152600160209081526040808320338085529252808320805460ff191690555188927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a3505050505050565b60026020526000908152604090205460ff1681565b600160209081526000928352604080842090915290825290205460ff1681565b60065481565b6000805b60055481101561090a578380156108d2575060008181526020819052604090206003015460ff16155b806108f657508280156108f6575060008181526020819052604090206003015460ff165b15610902576001820191505b6001016108a9565b5092915050565b604080517f72656d6f7665417574686f72697a65644164647265737328616464726573732981529051908190036020019020600090815b60048110156109a85781816004811061095d57fe5b1a60f860020a02600160f860020a031916848281518110151561097c57fe5b60209101015160f860020a9081900402600160f860020a031916146109a057600080fd5b600101610948565b600192505b5050919050565b600081815260208190526040812060030154829060ff16156109d557600080fd5b826109df81610cc5565b15156109ea57600080fd5b60008481526020819052604090206008548154869291600160a060020a03918216911614610a1757600080fd5b600281810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452610aac939291830182828015610aa25780601f10610a7757610100808354040283529160200191610aa2565b820191906000526020600020905b815481529060010190602001808311610a8557829003601f168201915b5050505050610911565b1515610ab757600080fd5b6000868152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959b50600160a060020a0390931695949293919283928592600019918316156101000291909101909116048015610b605780601f10610b3557610100808354040283529160200191610b60565b820191906000526020600020905b815481529060010190602001808311610b4357829003601f168201915b505091505060006040518083038185875af19250505015610b9957604051869060008051602061187683398151915290600090a2610bbf565b604051869060008051602061183683398151915290600090a260038501805460ff191690555b505050505050565b333014610bd357600080fd5b600160a060020a038116600090815260026020526040902054819060ff1615610bfb57600080fd5b81600160a060020a0381161515610c1157600080fd5b6003805490506001016004546032821180610c2b57508181115b80610c34575080155b80610c3d575081155b15610c4757600080fd5b600160a060020a038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b018054600160a060020a03191684179055516000805160206118568339815191529190a25050505050565b600080805b6003548110156109ad5760008481526001602052604081206003805491929184908110610cf357fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610d27576001820191505b600454821415610d3a57600192506109ad565b600101610cca565b333014610d4e57600080fd5b60068190556040805182815290517fd1c9101a34feff75cccef14a28785a0279cb0b49c1f321f21f5f422e746b43779181900360200190a150565b6000805b600354811015610df25760008381526001602052604081206003805491929184908110610db657fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610dea576001820191505b600101610d8d565b50919050565b6000602081815291815260409081902080546001808301546002808501805487516101009582161595909502600019011691909104601f8101889004880284018801909652858352600160a060020a0390931695909491929190830182828015610ea35780601f10610e7857610100808354040283529160200191610ea3565b820191906000526020600020905b815481529060010190602001808311610e8657829003601f168201915b5050506003909301549192505060ff1684565b60606003805480602002602001604051908101604052809291908181526020018280548015610f0e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610ef0575b505050505090505b90565b606080600080600554604051908082528060200260200182016040528015610f4b578160200160208202803883390190505b50925060009150600090505b600554811015610fd257858015610f80575060008181526020819052604090206003015460ff16155b80610fa45750848015610fa4575060008181526020819052604090206003015460ff165b15610fca57808383815181101515610fb857fe5b60209081029091010152600191909101905b600101610f57565b878703604051908082528060200260200182016040528015610ffe578160200160208202803883390190505b5093508790505b8681101561104757828181518110151561101b57fe5b906020019060200201518489830381518110151561103557fe5b60209081029091010152600101611005565b505050949350505050565b600854600160a060020a031681565b606080600080600380549050604051908082528060200260200182016040528015611096578160200160208202803883390190505b50925060009150600090505b60035481101561115357600085815260016020526040812060038054919291849081106110cb57fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff161561114b57600380548290811061110657fe5b6000918252602090912001548351600160a060020a039091169084908490811061112c57fe5b600160a060020a03909216602092830290910190910152600191909101905b6001016110a2565b8160405190808252806020026020018201604052801561117d578160200160208202803883390190505b509350600090505b818110156111d257828181518110151561119b57fe5b9060200190602002015184828151811015156111b357fe5b600160a060020a03909216602092830290910190910152600101611185565b505050919050565b60055481565b3330146111ec57600080fd5b6003548160328211806111fe57508181115b80611207575080155b80611210575081155b1561121a57600080fd5b60048390556040805184815290517fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9181900360200190a1505050565b3360008181526002602052604090205460ff16151561127557600080fd5b6000828152602081905260409020548290600160a060020a0316151561129a57600080fd5b60008381526001602090815260408083203380855292529091205484919060ff16156112c557600080fd5b846112cf81610cc5565b156112d957600080fd5b6000868152600160208181526040808420338086529252808420805460ff1916909317909255905188927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a361132f86610cc5565b15610bbf57610bbf8642611646565b600061134b848484611691565b905061135681611257565b9392505050565b60076020526000908152604090205481565b603281565b60045481565b600033301461138857600080fd5b600160a060020a038316600090815260026020526040902054839060ff1615156113b157600080fd5b600160a060020a038316600090815260026020526040902054839060ff16156113d957600080fd5b600092505b60035483101561146a5784600160a060020a031660038481548110151561140157fe5b600091825260209091200154600160a060020a0316141561145f578360038481548110151561142c57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a0316021790555061146a565b6001909201916113de565b600160a060020a03808616600081815260026020526040808220805460ff19908116909155938816825280822080549094166001179093559151909160008051602061189683398151915291a2604051600160a060020a0385169060008051602061185683398151915290600090a25050505050565b600081815260208190526040812060030154829060ff161561150157600080fd5b8261150b81610cc5565b151561151657600080fd5b60065460008581526007602052604090205485910142101561153757600080fd5b6000858152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959a50600160a060020a03909316959492939192839285926000199183161561010002919091019091160480156115e05780601f106115b5576101008083540402835291602001916115e0565b820191906000526020600020905b8154815290600101906020018083116115c357829003601f168201915b505091505060006040518083038185875af1925050501561161957604051859060008051602061187683398151915290600090a261163f565b604051859060008051602061183683398151915290600090a260038401805460ff191690555b5050505050565b6000828152600760209081526040918290208390558151838152915184927f0b237afe65f1514fd7ea3f923ea4fe792bdd07000a912b6cd1602a8e7f573c8d92908290030190a25050565b600083600160a060020a03811615156116a957600080fd5b60055460408051608081018252600160a060020a03888116825260208083018981528385018981526000606086018190528781528084529590952084518154600160a060020a0319169416939093178355516001830155925180519496509193909261171c92600285019291019061179d565b50606091909101516003909101805460ff191691151591909117905560058054600101905560405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b8154818355818111156117985760008381526020902061179891810190830161181b565b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106117de57805160ff191683800117855561180b565b8280016001018555821561180b579182015b8281111561180b5782518255916020019190600101906117f0565b5061181792915061181b565b5090565b610f1691905b8082111561181757600081556001016118215600526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b79236f39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed758001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b90a165627a7a723058200853bb251860c92945a3c94ebbaa86cbe3f8b7ed5e95b484f428752638c133800029", - "opcodes": - "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1B27 CODESIZE SUB DUP1 PUSH3 0x1B27 DUP4 CODECOPY DUP2 ADD PUSH1 0x40 SWAP1 DUP2 MSTORE DUP2 MLOAD PUSH1 0x20 DUP4 ADD MLOAD SWAP2 DUP4 ADD MLOAD PUSH1 0x60 DUP5 ADD MLOAD SWAP2 SWAP1 SWAP4 ADD DUP1 MLOAD SWAP1 SWAP4 SWAP2 SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP4 SWAP1 DUP4 SWAP1 PUSH1 0x0 SWAP1 DUP3 PUSH1 0x32 DUP3 GT DUP1 PUSH3 0x60 JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH3 0x6A JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH3 0x74 JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH3 0x7F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 SWAP3 POP JUMPDEST DUP5 MLOAD DUP4 LT ISZERO PUSH3 0x153 JUMPI PUSH1 0x2 PUSH1 0x0 DUP7 DUP6 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0xA1 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD DUP2 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP3 MSTORE DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH1 0xFF AND DUP1 PUSH3 0xF4 JUMPI POP DUP5 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0xDD JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x0 EQ JUMPDEST ISZERO PUSH3 0xFF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0x2 PUSH1 0x0 DUP8 DUP7 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x114 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP2 SWAP1 SWAP2 ADD DUP2 ADD MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP3 MSTORE DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 ADD PUSH1 0x0 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP2 ISZERO ISZERO SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH1 0x1 SWAP3 SWAP1 SWAP3 ADD SWAP2 PUSH3 0x84 JUMP JUMPDEST DUP5 MLOAD PUSH3 0x168 SWAP1 PUSH1 0x3 SWAP1 PUSH1 0x20 DUP9 ADD SWAP1 PUSH3 0x1A2 JUMP JUMPDEST POP POP POP PUSH1 0x4 SWAP2 SWAP1 SWAP2 SSTORE POP POP PUSH1 0x6 SSTORE POP POP PUSH1 0x8 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP3 SWAP1 SWAP3 AND SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE POP PUSH3 0x236 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD DUP3 DUP3 SSTORE SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 DUP2 ADD SWAP3 DUP3 ISZERO PUSH3 0x1FA JUMPI SWAP2 PUSH1 0x20 MUL DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x1FA JUMPI DUP3 MLOAD DUP3 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP2 AND OR DUP3 SSTORE PUSH1 0x20 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH3 0x1C3 JUMP JUMPDEST POP PUSH3 0x208 SWAP3 SWAP2 POP PUSH3 0x20C JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x233 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x208 JUMPI DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND DUP2 SSTORE PUSH1 0x1 ADD PUSH3 0x213 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x18E1 DUP1 PUSH3 0x246 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x145 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x25E7C27 DUP2 EQ PUSH2 0x187 JUMPI DUP1 PUSH4 0x173825D9 EQ PUSH2 0x1BB JUMPI DUP1 PUSH4 0x20EA8D86 EQ PUSH2 0x1DC JUMPI DUP1 PUSH4 0x2F54BF6E EQ PUSH2 0x1F4 JUMPI DUP1 PUSH4 0x3411C81C EQ PUSH2 0x229 JUMPI DUP1 PUSH4 0x37BD78A0 EQ PUSH2 0x24D JUMPI DUP1 PUSH4 0x54741525 EQ PUSH2 0x274 JUMPI DUP1 PUSH4 0x553A48FD EQ PUSH2 0x293 JUMPI DUP1 PUSH4 0x5711B311 EQ PUSH2 0x2EC JUMPI DUP1 PUSH4 0x7065CB48 EQ PUSH2 0x304 JUMPI DUP1 PUSH4 0x784547A7 EQ PUSH2 0x325 JUMPI DUP1 PUSH4 0x7AD28C51 EQ PUSH2 0x33D JUMPI DUP1 PUSH4 0x8B51D13F EQ PUSH2 0x355 JUMPI DUP1 PUSH4 0x9ACE38C2 EQ PUSH2 0x36D JUMPI DUP1 PUSH4 0xA0E67E2B EQ PUSH2 0x428 JUMPI DUP1 PUSH4 0xA8ABE69A EQ PUSH2 0x48D JUMPI DUP1 PUSH4 0xADD1CBC5 EQ PUSH2 0x4B2 JUMPI DUP1 PUSH4 0xB5DC40C3 EQ PUSH2 0x4C7 JUMPI DUP1 PUSH4 0xB77BF600 EQ PUSH2 0x4DF JUMPI DUP1 PUSH4 0xBA51A6DF EQ PUSH2 0x4F4 JUMPI DUP1 PUSH4 0xC01A8C84 EQ PUSH2 0x50C JUMPI DUP1 PUSH4 0xC6427474 EQ PUSH2 0x524 JUMPI DUP1 PUSH4 0xD38F2D82 EQ PUSH2 0x58D JUMPI DUP1 PUSH4 0xD74F8EDD EQ PUSH2 0x5A5 JUMPI DUP1 PUSH4 0xDC8452CD EQ PUSH2 0x5BA JUMPI DUP1 PUSH4 0xE20056E6 EQ PUSH2 0x5CF JUMPI DUP1 PUSH4 0xEE22610B EQ PUSH2 0x5F6 JUMPI JUMPDEST PUSH1 0x0 CALLVALUE GT ISZERO PUSH2 0x185 JUMPI PUSH1 0x40 DUP1 MLOAD CALLVALUE DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0xE1FFFCC4923D04B559F4D29A8BFC6CDA04EB5B0D3C460751C2402C5C5CC9109C SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x193 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH1 0x4 CALLDATALOAD PUSH2 0x60E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x636 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1E8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x79B JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x200 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x86A JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x235 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x24 CALLDATALOAD AND PUSH2 0x87F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x259 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x89F JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x280 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD ISZERO ISZERO PUSH1 0x24 CALLDATALOAD ISZERO ISZERO PUSH2 0x8A5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x29F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 DUP1 CALLDATALOAD DUP1 DUP3 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x215 SWAP5 CALLDATASIZE SWAP5 SWAP3 SWAP4 PUSH1 0x24 SWAP4 SWAP3 DUP5 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x911 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x9B4 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x310 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0xBC7 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x331 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH2 0xCC5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x349 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0xD42 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x361 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0xD89 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x379 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x385 PUSH1 0x4 CALLDATALOAD PUSH2 0xDF8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP6 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x20 ADD DUP5 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x3EA JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x3D2 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x417 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP6 POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x434 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH2 0xEB6 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 DUP2 ADD SWAP2 MUL DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x479 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x461 JUMP JUMPDEST POP POP POP POP SWAP1 POP ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x499 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH1 0x24 CALLDATALOAD PUSH1 0x44 CALLDATALOAD ISZERO ISZERO PUSH1 0x64 CALLDATALOAD ISZERO ISZERO PUSH2 0xF19 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4BE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH2 0x1052 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4D3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH2 0x1061 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4EB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x11DA JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x500 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x11E0 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x518 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x1257 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x530 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 PUSH1 0x44 CALLDATALOAD DUP2 DUP2 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x262 SWAP5 DUP3 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP5 PUSH1 0x24 DUP1 CALLDATALOAD SWAP6 CALLDATASIZE SWAP6 SWAP5 PUSH1 0x64 SWAP5 SWAP3 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x133E SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x599 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0x135D JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x136F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5C6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x1374 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH2 0x137A JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x602 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x14E0 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x61C JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 POP DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x644 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x66D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE SWAP2 POP JUMPDEST PUSH1 0x3 SLOAD PUSH1 0x0 NOT ADD DUP3 LT ISZERO PUSH2 0x748 JUMPI DUP3 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x6B7 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x73D JUMPI PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT DUP2 ADD SWAP1 DUP2 LT PUSH2 0x6E4 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x70A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x748 JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH2 0x690 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT ADD SWAP1 PUSH2 0x75B SWAP1 DUP3 PUSH2 0x1774 JUMP JUMPDEST POP PUSH1 0x3 SLOAD PUSH1 0x4 SLOAD GT ISZERO PUSH2 0x774 JUMPI PUSH1 0x3 SLOAD PUSH2 0x774 SWAP1 PUSH2 0x11E0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP5 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7B9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP4 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7E5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD DUP5 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x806 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x810 DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x81A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE DUP1 DUP4 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE MLOAD DUP9 SWAP3 PUSH32 0xF6A317157440607F36269043EB55F1287A5A19BA2216AFEAB88CD46CBCFB88E9 SWAP2 LOG3 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x0 SWAP3 DUP4 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 SWAP1 SWAP2 MSTORE SWAP1 DUP3 MSTORE SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0x90A JUMPI DUP4 DUP1 ISZERO PUSH2 0x8D2 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0x8F6 JUMPI POP DUP3 DUP1 ISZERO PUSH2 0x8F6 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0x902 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0x8A9 JUMP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x72656D6F7665417574686F72697A656441646472657373286164647265737329 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 KECCAK256 PUSH1 0x0 SWAP1 DUP2 JUMPDEST PUSH1 0x4 DUP2 LT ISZERO PUSH2 0x9A8 JUMPI DUP2 DUP2 PUSH1 0x4 DUP2 LT PUSH2 0x95D JUMPI INVALID JUMPDEST BYTE PUSH1 0xF8 PUSH1 0x2 EXP MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x97C JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP2 ADD ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND EQ PUSH2 0x9A0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 ADD PUSH2 0x948 JUMP JUMPDEST PUSH1 0x1 SWAP3 POP JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x9D5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x9DF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x9EA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x8 SLOAD DUP2 SLOAD DUP7 SWAP3 SWAP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP2 DUP3 AND SWAP2 AND EQ PUSH2 0xA17 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x2 DUP2 DUP2 ADD DUP1 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x1 DUP5 AND ISZERO PUSH2 0x100 MUL PUSH1 0x0 NOT ADD SWAP1 SWAP4 AND SWAP5 SWAP1 SWAP5 DIV PUSH1 0x1F DUP2 ADD DUP4 SWAP1 DIV DUP4 MUL DUP6 ADD DUP4 ADD SWAP1 SWAP2 MSTORE DUP1 DUP5 MSTORE PUSH2 0xAAC SWAP4 SWAP3 SWAP2 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xAA2 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA77 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAA2 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA85 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP PUSH2 0x911 JUMP JUMPDEST ISZERO ISZERO PUSH2 0xAB7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP12 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0xB60 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB35 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB60 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB43 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0xB99 JUMPI PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0xBBF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP6 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP POP JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xBD3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0xBFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0xC11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x1 ADD PUSH1 0x4 SLOAD PUSH1 0x32 DUP3 GT DUP1 PUSH2 0xC2B JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0xC34 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0xC3D JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0xC47 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE PUSH1 0x3 DUP1 SLOAD SWAP2 DUP3 ADD DUP2 SSTORE DUP4 MSTORE PUSH32 0xC2575A0E9E593C00F959F8C92F12DB2869C3395A3B0502D05E2516446F71F85B ADD DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND DUP5 OR SWAP1 SSTORE MLOAD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x9AD JUMPI PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xCF3 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xD27 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x4 SLOAD DUP3 EQ ISZERO PUSH2 0xD3A JUMPI PUSH1 0x1 SWAP3 POP PUSH2 0x9AD JUMP JUMPDEST PUSH1 0x1 ADD PUSH2 0xCCA JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xD4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 DUP2 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP3 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xD1C9101A34FEFF75CCCEF14A28785A0279CB0B49C1F321F21F5F422E746B4377 SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0xDF2 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xDB6 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xDEA JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0xD8D JUMP JUMPDEST POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP2 DUP2 MSTORE SWAP2 DUP2 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 DUP1 SLOAD PUSH1 0x1 DUP1 DUP4 ADD SLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD DUP8 MLOAD PUSH2 0x100 SWAP6 DUP3 AND ISZERO SWAP6 SWAP1 SWAP6 MUL PUSH1 0x0 NOT ADD AND SWAP2 SWAP1 SWAP2 DIV PUSH1 0x1F DUP2 ADD DUP9 SWAP1 DIV DUP9 MUL DUP5 ADD DUP9 ADD SWAP1 SWAP7 MSTORE DUP6 DUP4 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP1 SWAP5 SWAP2 SWAP3 SWAP2 SWAP1 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xEA3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xE78 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xEA3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xE86 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP PUSH1 0x3 SWAP1 SWAP4 ADD SLOAD SWAP2 SWAP3 POP POP PUSH1 0xFF AND DUP5 JUMP JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD DUP1 ISZERO PUSH2 0xF0E JUMPI PUSH1 0x20 MUL DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xEF0 JUMPI JUMPDEST POP POP POP POP POP SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x5 SLOAD PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xF4B JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0xFD2 JUMPI DUP6 DUP1 ISZERO PUSH2 0xF80 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0xFA4 JUMPI POP DUP5 DUP1 ISZERO PUSH2 0xFA4 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0xFCA JUMPI DUP1 DUP4 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xFB8 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0xF57 JUMP JUMPDEST DUP8 DUP8 SUB PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xFFE JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP DUP8 SWAP1 POP JUMPDEST DUP7 DUP2 LT ISZERO PUSH2 0x1047 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP10 DUP4 SUB DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1035 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1005 JUMP JUMPDEST POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x8 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x1096 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x1153 JUMPI PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x10CB JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0x114B JUMPI PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x1106 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP2 AND SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP2 LT PUSH2 0x112C JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0x10A2 JUMP JUMPDEST DUP2 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x117D JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP2 DUP2 LT ISZERO PUSH2 0x11D2 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x119B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x11B3 JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1185 JUMP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x5 SLOAD DUP2 JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0x11EC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 SLOAD DUP2 PUSH1 0x32 DUP3 GT DUP1 PUSH2 0x11FE JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0x1207 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0x1210 JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0x121A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x4 DUP4 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xA3F1EE9126A074D9326C682F561767F710E927FAA811F7A99829D49DC421797A SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x1275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND ISZERO ISZERO PUSH2 0x129A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP5 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x12C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x12CF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x12D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 DUP2 DUP2 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 CALLER DUP1 DUP7 MSTORE SWAP3 MSTORE DUP1 DUP5 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SWAP4 OR SWAP1 SWAP3 SSTORE SWAP1 MLOAD DUP9 SWAP3 PUSH32 0x4A504A94899432A9846E1AA406DCEB1BCFD538BB839071D49D1E5E23F5BE30EF SWAP2 LOG3 PUSH2 0x132F DUP7 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0xBBF JUMPI PUSH2 0xBBF DUP7 TIMESTAMP PUSH2 0x1646 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x134B DUP5 DUP5 DUP5 PUSH2 0x1691 JUMP JUMPDEST SWAP1 POP PUSH2 0x1356 DUP2 PUSH2 0x1257 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x32 DUP2 JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x1388 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x13B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x13D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 SWAP3 POP JUMPDEST PUSH1 0x3 SLOAD DUP4 LT ISZERO PUSH2 0x146A JUMPI DUP5 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1401 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x145F JUMPI DUP4 PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x142C JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x146A JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP3 ADD SWAP2 PUSH2 0x13DE JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP1 DUP7 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT SWAP1 DUP2 AND SWAP1 SWAP2 SSTORE SWAP4 DUP9 AND DUP3 MSTORE DUP1 DUP3 KECCAK256 DUP1 SLOAD SWAP1 SWAP5 AND PUSH1 0x1 OR SWAP1 SWAP4 SSTORE SWAP2 MLOAD SWAP1 SWAP2 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 LOG2 PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x1501 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x150B DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x1516 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 SLOAD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP6 SWAP2 ADD TIMESTAMP LT ISZERO PUSH2 0x1537 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP11 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0x15E0 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x15B5 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x15E0 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x15C3 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0x1619 JUMPI PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0x163F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP5 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP2 DUP3 SWAP1 KECCAK256 DUP4 SWAP1 SSTORE DUP2 MLOAD DUP4 DUP2 MSTORE SWAP2 MLOAD DUP5 SWAP3 PUSH32 0xB237AFE65F1514FD7EA3F923EA4FE792BDD07000A912B6CD1602A8E7F573C8D SWAP3 SWAP1 DUP3 SWAP1 SUB ADD SWAP1 LOG2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0x16A9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x5 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP9 DUP2 AND DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 ADD DUP10 DUP2 MSTORE DUP4 DUP6 ADD DUP10 DUP2 MSTORE PUSH1 0x0 PUSH1 0x60 DUP7 ADD DUP2 SWAP1 MSTORE DUP8 DUP2 MSTORE DUP1 DUP5 MSTORE SWAP6 SWAP1 SWAP6 KECCAK256 DUP5 MLOAD DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND SWAP5 AND SWAP4 SWAP1 SWAP4 OR DUP4 SSTORE MLOAD PUSH1 0x1 DUP4 ADD SSTORE SWAP3 MLOAD DUP1 MLOAD SWAP5 SWAP7 POP SWAP2 SWAP4 SWAP1 SWAP3 PUSH2 0x171C SWAP3 PUSH1 0x2 DUP6 ADD SWAP3 SWAP2 ADD SWAP1 PUSH2 0x179D JUMP JUMPDEST POP PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD MLOAD PUSH1 0x3 SWAP1 SWAP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP2 ISZERO ISZERO SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE PUSH1 0x40 MLOAD DUP3 SWAP1 PUSH32 0xC0BA8FE4B176C1714197D43B9CC6BCF797A4A7461C5FE8D0EF6E184AE7601E51 SWAP1 PUSH1 0x0 SWAP1 LOG2 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 GT ISZERO PUSH2 0x1798 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x20 SWAP1 KECCAK256 PUSH2 0x1798 SWAP2 DUP2 ADD SWAP1 DUP4 ADD PUSH2 0x181B JUMP JUMPDEST POP POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x17DE JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x180B JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x180B JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x180B JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x17F0 JUMP JUMPDEST POP PUSH2 0x1817 SWAP3 SWAP2 POP PUSH2 0x181B JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH2 0xF16 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1817 JUMPI PUSH1 0x0 DUP2 SSTORE PUSH1 0x1 ADD PUSH2 0x1821 JUMP STOP MSTORE PUSH5 0x41BB6C1ABA EXTCODECOPY SWAP11 0x4a PUSH13 0xA1D6545DA9C2333C8C48343EF3 SWAP9 0xeb DUP6 DUP14 PUSH19 0xB79236F39E6E1EB0EDCF53C221607B54B00CD2 DUP16 BALANCE SWAP7 INVALID 0xd0 LOG2 0x49 SWAP5 0xdc ADDRESS DUP12 DUP16 PUSH2 0x1B68 0x2d CALLER 0xe1 RETURNDATACOPY 0xcb SLOAD 0xc3 SMOD PUSH14 0x8E8BB8C2881800A4D972B792045F STATICCALL 0xe9 DUP16 0xdf 0x46 0xdf CALLDATASIZE 0x5f 0xed PUSH22 0x8001553A916EF2F495D26A907CC54D96ED840D7BDA71 0xe7 BALANCE SWAP5 0xbf GAS SWAP14 0xf7 0xa7 PUSH12 0x90A165627A7A723058200853 0xbb 0x25 XOR PUSH1 0xC9 0x29 GASLIMIT LOG3 0xc9 0x4e 0xbb 0xaa DUP7 0xcb 0xe3 0xf8 0xb7 0xed 0x5e SWAP6 0xb4 DUP5 DELEGATECALL 0x28 PUSH22 0x2638C133800029000000000000000000000000000000 ", - "sourceMap": - "714:2422:2:-;;;1582:349;8:9:-1;5:2;;;30:1;27;20:12;5:2;1582:349:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2913:14:0;;1582:349:2;;;;;;;;;;;;;;2959:6:0;;1582:349:2;256:2:0;2236:28;;;:66;;;2292:10;2280:9;:22;2236:66;:96;;;-1:-1:-1;2318:14:0;;2236:96;:127;;;-1:-1:-1;2348:15:0;;2236:127;2229:153;;;2377:5;;;2229:153;2966:1;2959:8;;2954:168;2971:7;:14;2969:1;:16;2954:168;;;3010:7;:19;3018:7;3026:1;3018:10;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3010:19:0;;;;;;;;;;;-1:-1:-1;3010:19:0;;;;;:38;;;3033:7;3041:1;3033:10;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3033:15:0;3047:1;3033:15;3010:38;3006:65;;;3066:5;;;3006:65;3107:4;3085:7;:19;3093:7;3101:1;3093:10;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3085:19:0;;;;;;;;;;;-1:-1:-1;3085:19:0;:26;;-1:-1:-1;;3085:26:0;;;;;;;;;;-1:-1:-1;2987:3:0;;;;;2954:168;;;3131:16;;;;:6;;:16;;;;;:::i;:::-;-1:-1:-1;;;3157:8:0;:20;;;;-1:-1:-1;;2072:17:1;:38;-1:-1:-1;;1873:29:2;:51;;-1:-1:-1;;;;;;1873:51:2;-1:-1:-1;;;;;1873:51:2;;;;;;;;;;-1:-1:-1;714:2422:2;;-1:-1:-1;;714:2422:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;714:2422:2;-1:-1:-1;;;;;714:2422:2;;;;;;;;;;;-1:-1:-1;714:2422:2;;;;;;;-1:-1:-1;714:2422:2;;;-1:-1:-1;714:2422:2;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;;714:2422:2;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": - "0x6080604052600436106101455763ffffffff60e060020a600035041663025e7c278114610187578063173825d9146101bb57806320ea8d86146101dc5780632f54bf6e146101f45780633411c81c1461022957806337bd78a01461024d5780635474152514610274578063553a48fd146102935780635711b311146102ec5780637065cb4814610304578063784547a7146103255780637ad28c511461033d5780638b51d13f146103555780639ace38c21461036d578063a0e67e2b14610428578063a8abe69a1461048d578063add1cbc5146104b2578063b5dc40c3146104c7578063b77bf600146104df578063ba51a6df146104f4578063c01a8c841461050c578063c642747414610524578063d38f2d821461058d578063d74f8edd146105a5578063dc8452cd146105ba578063e20056e6146105cf578063ee22610b146105f6575b60003411156101855760408051348152905133917fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c919081900360200190a25b005b34801561019357600080fd5b5061019f60043561060e565b60408051600160a060020a039092168252519081900360200190f35b3480156101c757600080fd5b50610185600160a060020a0360043516610636565b3480156101e857600080fd5b5061018560043561079b565b34801561020057600080fd5b50610215600160a060020a036004351661086a565b604080519115158252519081900360200190f35b34801561023557600080fd5b50610215600435600160a060020a036024351661087f565b34801561025957600080fd5b5061026261089f565b60408051918252519081900360200190f35b34801561028057600080fd5b50610262600435151560243515156108a5565b34801561029f57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102159436949293602493928401919081908401838280828437509497506109119650505050505050565b3480156102f857600080fd5b506101856004356109b4565b34801561031057600080fd5b50610185600160a060020a0360043516610bc7565b34801561033157600080fd5b50610215600435610cc5565b34801561034957600080fd5b50610185600435610d42565b34801561036157600080fd5b50610262600435610d89565b34801561037957600080fd5b50610385600435610df8565b6040518085600160a060020a0316600160a060020a031681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156103ea5781810151838201526020016103d2565b50505050905090810190601f1680156104175780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561043457600080fd5b5061043d610eb6565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610479578181015183820152602001610461565b505050509050019250505060405180910390f35b34801561049957600080fd5b5061043d60043560243560443515156064351515610f19565b3480156104be57600080fd5b5061019f611052565b3480156104d357600080fd5b5061043d600435611061565b3480156104eb57600080fd5b506102626111da565b34801561050057600080fd5b506101856004356111e0565b34801561051857600080fd5b50610185600435611257565b34801561053057600080fd5b50604080516020600460443581810135601f8101849004840285018401909552848452610262948235600160a060020a031694602480359536959460649492019190819084018382808284375094975061133e9650505050505050565b34801561059957600080fd5b5061026260043561135d565b3480156105b157600080fd5b5061026261136f565b3480156105c657600080fd5b50610262611374565b3480156105db57600080fd5b50610185600160a060020a036004358116906024351661137a565b34801561060257600080fd5b506101856004356114e0565b600380548290811061061c57fe5b600091825260209091200154600160a060020a0316905081565b600033301461064457600080fd5b600160a060020a038216600090815260026020526040902054829060ff16151561066d57600080fd5b600160a060020a0383166000908152600260205260408120805460ff1916905591505b600354600019018210156107485782600160a060020a03166003838154811015156106b757fe5b600091825260209091200154600160a060020a0316141561073d576003805460001981019081106106e457fe5b60009182526020909120015460038054600160a060020a03909216918490811061070a57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a03160217905550610748565b600190910190610690565b60038054600019019061075b9082611774565b50600354600454111561077457600354610774906111e0565b604051600160a060020a0384169060008051602061189683398151915290600090a2505050565b3360008181526002602052604090205460ff1615156107b957600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1615156107e557600080fd5b600084815260208190526040902060030154849060ff161561080657600080fd5b8461081081610cc5565b1561081a57600080fd5b6000868152600160209081526040808320338085529252808320805460ff191690555188927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a3505050505050565b60026020526000908152604090205460ff1681565b600160209081526000928352604080842090915290825290205460ff1681565b60065481565b6000805b60055481101561090a578380156108d2575060008181526020819052604090206003015460ff16155b806108f657508280156108f6575060008181526020819052604090206003015460ff165b15610902576001820191505b6001016108a9565b5092915050565b604080517f72656d6f7665417574686f72697a65644164647265737328616464726573732981529051908190036020019020600090815b60048110156109a85781816004811061095d57fe5b1a60f860020a02600160f860020a031916848281518110151561097c57fe5b60209101015160f860020a9081900402600160f860020a031916146109a057600080fd5b600101610948565b600192505b5050919050565b600081815260208190526040812060030154829060ff16156109d557600080fd5b826109df81610cc5565b15156109ea57600080fd5b60008481526020819052604090206008548154869291600160a060020a03918216911614610a1757600080fd5b600281810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452610aac939291830182828015610aa25780601f10610a7757610100808354040283529160200191610aa2565b820191906000526020600020905b815481529060010190602001808311610a8557829003601f168201915b5050505050610911565b1515610ab757600080fd5b6000868152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959b50600160a060020a0390931695949293919283928592600019918316156101000291909101909116048015610b605780601f10610b3557610100808354040283529160200191610b60565b820191906000526020600020905b815481529060010190602001808311610b4357829003601f168201915b505091505060006040518083038185875af19250505015610b9957604051869060008051602061187683398151915290600090a2610bbf565b604051869060008051602061183683398151915290600090a260038501805460ff191690555b505050505050565b333014610bd357600080fd5b600160a060020a038116600090815260026020526040902054819060ff1615610bfb57600080fd5b81600160a060020a0381161515610c1157600080fd5b6003805490506001016004546032821180610c2b57508181115b80610c34575080155b80610c3d575081155b15610c4757600080fd5b600160a060020a038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b018054600160a060020a03191684179055516000805160206118568339815191529190a25050505050565b600080805b6003548110156109ad5760008481526001602052604081206003805491929184908110610cf357fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610d27576001820191505b600454821415610d3a57600192506109ad565b600101610cca565b333014610d4e57600080fd5b60068190556040805182815290517fd1c9101a34feff75cccef14a28785a0279cb0b49c1f321f21f5f422e746b43779181900360200190a150565b6000805b600354811015610df25760008381526001602052604081206003805491929184908110610db657fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610dea576001820191505b600101610d8d565b50919050565b6000602081815291815260409081902080546001808301546002808501805487516101009582161595909502600019011691909104601f8101889004880284018801909652858352600160a060020a0390931695909491929190830182828015610ea35780601f10610e7857610100808354040283529160200191610ea3565b820191906000526020600020905b815481529060010190602001808311610e8657829003601f168201915b5050506003909301549192505060ff1684565b60606003805480602002602001604051908101604052809291908181526020018280548015610f0e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610ef0575b505050505090505b90565b606080600080600554604051908082528060200260200182016040528015610f4b578160200160208202803883390190505b50925060009150600090505b600554811015610fd257858015610f80575060008181526020819052604090206003015460ff16155b80610fa45750848015610fa4575060008181526020819052604090206003015460ff165b15610fca57808383815181101515610fb857fe5b60209081029091010152600191909101905b600101610f57565b878703604051908082528060200260200182016040528015610ffe578160200160208202803883390190505b5093508790505b8681101561104757828181518110151561101b57fe5b906020019060200201518489830381518110151561103557fe5b60209081029091010152600101611005565b505050949350505050565b600854600160a060020a031681565b606080600080600380549050604051908082528060200260200182016040528015611096578160200160208202803883390190505b50925060009150600090505b60035481101561115357600085815260016020526040812060038054919291849081106110cb57fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff161561114b57600380548290811061110657fe5b6000918252602090912001548351600160a060020a039091169084908490811061112c57fe5b600160a060020a03909216602092830290910190910152600191909101905b6001016110a2565b8160405190808252806020026020018201604052801561117d578160200160208202803883390190505b509350600090505b818110156111d257828181518110151561119b57fe5b9060200190602002015184828151811015156111b357fe5b600160a060020a03909216602092830290910190910152600101611185565b505050919050565b60055481565b3330146111ec57600080fd5b6003548160328211806111fe57508181115b80611207575080155b80611210575081155b1561121a57600080fd5b60048390556040805184815290517fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9181900360200190a1505050565b3360008181526002602052604090205460ff16151561127557600080fd5b6000828152602081905260409020548290600160a060020a0316151561129a57600080fd5b60008381526001602090815260408083203380855292529091205484919060ff16156112c557600080fd5b846112cf81610cc5565b156112d957600080fd5b6000868152600160208181526040808420338086529252808420805460ff1916909317909255905188927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a361132f86610cc5565b15610bbf57610bbf8642611646565b600061134b848484611691565b905061135681611257565b9392505050565b60076020526000908152604090205481565b603281565b60045481565b600033301461138857600080fd5b600160a060020a038316600090815260026020526040902054839060ff1615156113b157600080fd5b600160a060020a038316600090815260026020526040902054839060ff16156113d957600080fd5b600092505b60035483101561146a5784600160a060020a031660038481548110151561140157fe5b600091825260209091200154600160a060020a0316141561145f578360038481548110151561142c57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a0316021790555061146a565b6001909201916113de565b600160a060020a03808616600081815260026020526040808220805460ff19908116909155938816825280822080549094166001179093559151909160008051602061189683398151915291a2604051600160a060020a0385169060008051602061185683398151915290600090a25050505050565b600081815260208190526040812060030154829060ff161561150157600080fd5b8261150b81610cc5565b151561151657600080fd5b60065460008581526007602052604090205485910142101561153757600080fd5b6000858152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959a50600160a060020a03909316959492939192839285926000199183161561010002919091019091160480156115e05780601f106115b5576101008083540402835291602001916115e0565b820191906000526020600020905b8154815290600101906020018083116115c357829003601f168201915b505091505060006040518083038185875af1925050501561161957604051859060008051602061187683398151915290600090a261163f565b604051859060008051602061183683398151915290600090a260038401805460ff191690555b5050505050565b6000828152600760209081526040918290208390558151838152915184927f0b237afe65f1514fd7ea3f923ea4fe792bdd07000a912b6cd1602a8e7f573c8d92908290030190a25050565b600083600160a060020a03811615156116a957600080fd5b60055460408051608081018252600160a060020a03888116825260208083018981528385018981526000606086018190528781528084529590952084518154600160a060020a0319169416939093178355516001830155925180519496509193909261171c92600285019291019061179d565b50606091909101516003909101805460ff191691151591909117905560058054600101905560405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b8154818355818111156117985760008381526020902061179891810190830161181b565b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106117de57805160ff191683800117855561180b565b8280016001018555821561180b579182015b8281111561180b5782518255916020019190600101906117f0565b5061181792915061181b565b5090565b610f1691905b8082111561181757600081556001016118215600526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b79236f39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed758001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b90a165627a7a723058200853bb251860c92945a3c94ebbaa86cbe3f8b7ed5e95b484f428752638c133800029", - "opcodes": - "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x145 JUMPI PUSH4 0xFFFFFFFF PUSH1 0xE0 PUSH1 0x2 EXP PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x25E7C27 DUP2 EQ PUSH2 0x187 JUMPI DUP1 PUSH4 0x173825D9 EQ PUSH2 0x1BB JUMPI DUP1 PUSH4 0x20EA8D86 EQ PUSH2 0x1DC JUMPI DUP1 PUSH4 0x2F54BF6E EQ PUSH2 0x1F4 JUMPI DUP1 PUSH4 0x3411C81C EQ PUSH2 0x229 JUMPI DUP1 PUSH4 0x37BD78A0 EQ PUSH2 0x24D JUMPI DUP1 PUSH4 0x54741525 EQ PUSH2 0x274 JUMPI DUP1 PUSH4 0x553A48FD EQ PUSH2 0x293 JUMPI DUP1 PUSH4 0x5711B311 EQ PUSH2 0x2EC JUMPI DUP1 PUSH4 0x7065CB48 EQ PUSH2 0x304 JUMPI DUP1 PUSH4 0x784547A7 EQ PUSH2 0x325 JUMPI DUP1 PUSH4 0x7AD28C51 EQ PUSH2 0x33D JUMPI DUP1 PUSH4 0x8B51D13F EQ PUSH2 0x355 JUMPI DUP1 PUSH4 0x9ACE38C2 EQ PUSH2 0x36D JUMPI DUP1 PUSH4 0xA0E67E2B EQ PUSH2 0x428 JUMPI DUP1 PUSH4 0xA8ABE69A EQ PUSH2 0x48D JUMPI DUP1 PUSH4 0xADD1CBC5 EQ PUSH2 0x4B2 JUMPI DUP1 PUSH4 0xB5DC40C3 EQ PUSH2 0x4C7 JUMPI DUP1 PUSH4 0xB77BF600 EQ PUSH2 0x4DF JUMPI DUP1 PUSH4 0xBA51A6DF EQ PUSH2 0x4F4 JUMPI DUP1 PUSH4 0xC01A8C84 EQ PUSH2 0x50C JUMPI DUP1 PUSH4 0xC6427474 EQ PUSH2 0x524 JUMPI DUP1 PUSH4 0xD38F2D82 EQ PUSH2 0x58D JUMPI DUP1 PUSH4 0xD74F8EDD EQ PUSH2 0x5A5 JUMPI DUP1 PUSH4 0xDC8452CD EQ PUSH2 0x5BA JUMPI DUP1 PUSH4 0xE20056E6 EQ PUSH2 0x5CF JUMPI DUP1 PUSH4 0xEE22610B EQ PUSH2 0x5F6 JUMPI JUMPDEST PUSH1 0x0 CALLVALUE GT ISZERO PUSH2 0x185 JUMPI PUSH1 0x40 DUP1 MLOAD CALLVALUE DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0xE1FFFCC4923D04B559F4D29A8BFC6CDA04EB5B0D3C460751C2402C5C5CC9109C SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x193 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH1 0x4 CALLDATALOAD PUSH2 0x60E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x636 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1E8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x79B JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x200 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0x86A JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x235 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x24 CALLDATALOAD AND PUSH2 0x87F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x259 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x89F JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x280 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD ISZERO ISZERO PUSH1 0x24 CALLDATALOAD ISZERO ISZERO PUSH2 0x8A5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x29F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 DUP1 CALLDATALOAD DUP1 DUP3 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x215 SWAP5 CALLDATASIZE SWAP5 SWAP3 SWAP4 PUSH1 0x24 SWAP4 SWAP3 DUP5 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x911 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x2F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x9B4 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x310 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD AND PUSH2 0xBC7 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x331 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x215 PUSH1 0x4 CALLDATALOAD PUSH2 0xCC5 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x349 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0xD42 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x361 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0xD89 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x379 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x385 PUSH1 0x4 CALLDATALOAD PUSH2 0xDF8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP6 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x20 ADD DUP5 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x3EA JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x3D2 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x417 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP6 POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x434 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH2 0xEB6 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 DUP1 DUP3 MSTORE DUP4 MLOAD DUP2 DUP4 ADD MSTORE DUP4 MLOAD SWAP2 SWAP3 DUP4 SWAP3 SWAP1 DUP4 ADD SWAP2 DUP6 DUP2 ADD SWAP2 MUL DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x479 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x461 JUMP JUMPDEST POP POP POP POP SWAP1 POP ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x499 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH1 0x24 CALLDATALOAD PUSH1 0x44 CALLDATALOAD ISZERO ISZERO PUSH1 0x64 CALLDATALOAD ISZERO ISZERO PUSH2 0xF19 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4BE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x19F PUSH2 0x1052 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4D3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x43D PUSH1 0x4 CALLDATALOAD PUSH2 0x1061 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x4EB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x11DA JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x500 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x11E0 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x518 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x1257 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x530 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 PUSH1 0x44 CALLDATALOAD DUP2 DUP2 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0x262 SWAP5 DUP3 CALLDATALOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP5 PUSH1 0x24 DUP1 CALLDATALOAD SWAP6 CALLDATASIZE SWAP6 SWAP5 PUSH1 0x64 SWAP5 SWAP3 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0x133E SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x599 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH1 0x4 CALLDATALOAD PUSH2 0x135D JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x136F JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5C6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x262 PUSH2 0x1374 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB PUSH1 0x4 CALLDATALOAD DUP2 AND SWAP1 PUSH1 0x24 CALLDATALOAD AND PUSH2 0x137A JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x602 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x185 PUSH1 0x4 CALLDATALOAD PUSH2 0x14E0 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x61C JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 POP DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x644 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x66D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE SWAP2 POP JUMPDEST PUSH1 0x3 SLOAD PUSH1 0x0 NOT ADD DUP3 LT ISZERO PUSH2 0x748 JUMPI DUP3 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x6B7 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x73D JUMPI PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT DUP2 ADD SWAP1 DUP2 LT PUSH2 0x6E4 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x70A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x748 JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH2 0x690 JUMP JUMPDEST PUSH1 0x3 DUP1 SLOAD PUSH1 0x0 NOT ADD SWAP1 PUSH2 0x75B SWAP1 DUP3 PUSH2 0x1774 JUMP JUMPDEST POP PUSH1 0x3 SLOAD PUSH1 0x4 SLOAD GT ISZERO PUSH2 0x774 JUMPI PUSH1 0x3 SLOAD PUSH2 0x774 SWAP1 PUSH2 0x11E0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP5 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7B9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP4 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x7E5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD DUP5 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x806 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x810 DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x81A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE DUP1 DUP4 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE MLOAD DUP9 SWAP3 PUSH32 0xF6A317157440607F36269043EB55F1287A5A19BA2216AFEAB88CD46CBCFB88E9 SWAP2 LOG3 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x0 SWAP3 DUP4 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 SWAP1 SWAP2 MSTORE SWAP1 DUP3 MSTORE SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0x90A JUMPI DUP4 DUP1 ISZERO PUSH2 0x8D2 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0x8F6 JUMPI POP DUP3 DUP1 ISZERO PUSH2 0x8F6 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0x902 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0x8A9 JUMP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x72656D6F7665417574686F72697A656441646472657373286164647265737329 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 KECCAK256 PUSH1 0x0 SWAP1 DUP2 JUMPDEST PUSH1 0x4 DUP2 LT ISZERO PUSH2 0x9A8 JUMPI DUP2 DUP2 PUSH1 0x4 DUP2 LT PUSH2 0x95D JUMPI INVALID JUMPDEST BYTE PUSH1 0xF8 PUSH1 0x2 EXP MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x97C JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP2 ADD ADD MLOAD PUSH1 0xF8 PUSH1 0x2 EXP SWAP1 DUP2 SWAP1 DIV MUL PUSH1 0x1 PUSH1 0xF8 PUSH1 0x2 EXP SUB NOT AND EQ PUSH2 0x9A0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 ADD PUSH2 0x948 JUMP JUMPDEST PUSH1 0x1 SWAP3 POP JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x9D5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x9DF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x9EA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x8 SLOAD DUP2 SLOAD DUP7 SWAP3 SWAP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP2 DUP3 AND SWAP2 AND EQ PUSH2 0xA17 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x2 DUP2 DUP2 ADD DUP1 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x1 DUP5 AND ISZERO PUSH2 0x100 MUL PUSH1 0x0 NOT ADD SWAP1 SWAP4 AND SWAP5 SWAP1 SWAP5 DIV PUSH1 0x1F DUP2 ADD DUP4 SWAP1 DIV DUP4 MUL DUP6 ADD DUP4 ADD SWAP1 SWAP2 MSTORE DUP1 DUP5 MSTORE PUSH2 0xAAC SWAP4 SWAP3 SWAP2 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xAA2 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA77 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xAA2 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA85 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP PUSH2 0x911 JUMP JUMPDEST ISZERO ISZERO PUSH2 0xAB7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP12 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0xB60 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB35 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB60 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB43 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0xB99 JUMPI PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0xBBF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP7 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP6 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP POP JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xBD3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0xBFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0xC11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x1 ADD PUSH1 0x4 SLOAD PUSH1 0x32 DUP3 GT DUP1 PUSH2 0xC2B JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0xC34 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0xC3D JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0xC47 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE PUSH1 0x3 DUP1 SLOAD SWAP2 DUP3 ADD DUP2 SSTORE DUP4 MSTORE PUSH32 0xC2575A0E9E593C00F959F8C92F12DB2869C3395A3B0502D05E2516446F71F85B ADD DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND DUP5 OR SWAP1 SSTORE MLOAD PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x9AD JUMPI PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xCF3 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xD27 JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x4 SLOAD DUP3 EQ ISZERO PUSH2 0xD3A JUMPI PUSH1 0x1 SWAP3 POP PUSH2 0x9AD JUMP JUMPDEST PUSH1 0x1 ADD PUSH2 0xCCA JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0xD4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 DUP2 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP3 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xD1C9101A34FEFF75CCCEF14A28785A0279CB0B49C1F321F21F5F422E746B4377 SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0xDF2 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0xDB6 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0xDEA JUMPI PUSH1 0x1 DUP3 ADD SWAP2 POP JUMPDEST PUSH1 0x1 ADD PUSH2 0xD8D JUMP JUMPDEST POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP2 DUP2 MSTORE SWAP2 DUP2 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 DUP1 SLOAD PUSH1 0x1 DUP1 DUP4 ADD SLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD DUP8 MLOAD PUSH2 0x100 SWAP6 DUP3 AND ISZERO SWAP6 SWAP1 SWAP6 MUL PUSH1 0x0 NOT ADD AND SWAP2 SWAP1 SWAP2 DIV PUSH1 0x1F DUP2 ADD DUP9 SWAP1 DIV DUP9 MUL DUP5 ADD DUP9 ADD SWAP1 SWAP7 MSTORE DUP6 DUP4 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP1 SWAP5 SWAP2 SWAP3 SWAP2 SWAP1 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xEA3 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xE78 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xEA3 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xE86 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP PUSH1 0x3 SWAP1 SWAP4 ADD SLOAD SWAP2 SWAP3 POP POP PUSH1 0xFF AND DUP5 JUMP JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD DUP1 ISZERO PUSH2 0xF0E JUMPI PUSH1 0x20 MUL DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 MSTORE PUSH1 0x1 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xEF0 JUMPI JUMPDEST POP POP POP POP POP SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x5 SLOAD PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xF4B JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x5 SLOAD DUP2 LT ISZERO PUSH2 0xFD2 JUMPI DUP6 DUP1 ISZERO PUSH2 0xF80 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND ISZERO JUMPDEST DUP1 PUSH2 0xFA4 JUMPI POP DUP5 DUP1 ISZERO PUSH2 0xFA4 JUMPI POP PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 PUSH1 0x3 ADD SLOAD PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0xFCA JUMPI DUP1 DUP4 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xFB8 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0xF57 JUMP JUMPDEST DUP8 DUP8 SUB PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xFFE JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP DUP8 SWAP1 POP JUMPDEST DUP7 DUP2 LT ISZERO PUSH2 0x1047 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x101B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP10 DUP4 SUB DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1035 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1005 JUMP JUMPDEST POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x8 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP2 JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 DUP1 PUSH1 0x3 DUP1 SLOAD SWAP1 POP PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x1096 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP PUSH1 0x0 SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST PUSH1 0x3 SLOAD DUP2 LT ISZERO PUSH2 0x1153 JUMPI PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 DUP1 SLOAD SWAP2 SWAP3 SWAP2 DUP5 SWAP1 DUP2 LT PUSH2 0x10CB JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 KECCAK256 SWAP1 SWAP2 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND DUP4 MSTORE DUP3 ADD SWAP3 SWAP1 SWAP3 MSTORE PUSH1 0x40 ADD SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO PUSH2 0x114B JUMPI PUSH1 0x3 DUP1 SLOAD DUP3 SWAP1 DUP2 LT PUSH2 0x1106 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP2 AND SWAP1 DUP5 SWAP1 DUP5 SWAP1 DUP2 LT PUSH2 0x112C JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 SWAP2 SWAP1 SWAP2 ADD SWAP1 JUMPDEST PUSH1 0x1 ADD PUSH2 0x10A2 JUMP JUMPDEST DUP2 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x117D JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP4 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP2 DUP2 LT ISZERO PUSH2 0x11D2 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x119B JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP5 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x11B3 JUMPI INVALID JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x20 SWAP3 DUP4 MUL SWAP1 SWAP2 ADD SWAP1 SWAP2 ADD MSTORE PUSH1 0x1 ADD PUSH2 0x1185 JUMP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x5 SLOAD DUP2 JUMP JUMPDEST CALLER ADDRESS EQ PUSH2 0x11EC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3 SLOAD DUP2 PUSH1 0x32 DUP3 GT DUP1 PUSH2 0x11FE JUMPI POP DUP2 DUP2 GT JUMPDEST DUP1 PUSH2 0x1207 JUMPI POP DUP1 ISZERO JUMPDEST DUP1 PUSH2 0x1210 JUMPI POP DUP2 ISZERO JUMPDEST ISZERO PUSH2 0x121A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x4 DUP4 SWAP1 SSTORE PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xA3F1EE9126A074D9326C682F561767F710E927FAA811F7A99829D49DC421797A SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP POP POP JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x1275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP3 SWAP1 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND ISZERO ISZERO PUSH2 0x129A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 CALLER DUP1 DUP6 MSTORE SWAP3 MSTORE SWAP1 SWAP2 KECCAK256 SLOAD DUP5 SWAP2 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x12C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 PUSH2 0x12CF DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0x12D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP7 DUP2 MSTORE PUSH1 0x1 PUSH1 0x20 DUP2 DUP2 MSTORE PUSH1 0x40 DUP1 DUP5 KECCAK256 CALLER DUP1 DUP7 MSTORE SWAP3 MSTORE DUP1 DUP5 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SWAP4 OR SWAP1 SWAP3 SSTORE SWAP1 MLOAD DUP9 SWAP3 PUSH32 0x4A504A94899432A9846E1AA406DCEB1BCFD538BB839071D49D1E5E23F5BE30EF SWAP2 LOG3 PUSH2 0x132F DUP7 PUSH2 0xCC5 JUMP JUMPDEST ISZERO PUSH2 0xBBF JUMPI PUSH2 0xBBF DUP7 TIMESTAMP PUSH2 0x1646 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x134B DUP5 DUP5 DUP5 PUSH2 0x1691 JUMP JUMPDEST SWAP1 POP PUSH2 0x1356 DUP2 PUSH2 0x1257 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x32 DUP2 JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLER ADDRESS EQ PUSH2 0x1388 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO ISZERO PUSH2 0x13B1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP4 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP4 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x13D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 SWAP3 POP JUMPDEST PUSH1 0x3 SLOAD DUP4 LT ISZERO PUSH2 0x146A JUMPI DUP5 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1401 JUMPI INVALID JUMPDEST PUSH1 0x0 SWAP2 DUP3 MSTORE PUSH1 0x20 SWAP1 SWAP2 KECCAK256 ADD SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND EQ ISZERO PUSH2 0x145F JUMPI DUP4 PUSH1 0x3 DUP5 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x142C JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB MUL NOT AND SWAP1 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND MUL OR SWAP1 SSTORE POP PUSH2 0x146A JUMP JUMPDEST PUSH1 0x1 SWAP1 SWAP3 ADD SWAP2 PUSH2 0x13DE JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP1 DUP7 AND PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 DUP1 SLOAD PUSH1 0xFF NOT SWAP1 DUP2 AND SWAP1 SWAP2 SSTORE SWAP4 DUP9 AND DUP3 MSTORE DUP1 DUP3 KECCAK256 DUP1 SLOAD SWAP1 SWAP5 AND PUSH1 0x1 OR SWAP1 SWAP4 SSTORE SWAP2 MLOAD SWAP1 SWAP2 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1896 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP2 LOG2 PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP6 AND SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1856 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 DUP2 KECCAK256 PUSH1 0x3 ADD SLOAD DUP3 SWAP1 PUSH1 0xFF AND ISZERO PUSH2 0x1501 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 PUSH2 0x150B DUP2 PUSH2 0xCC5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x1516 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x6 SLOAD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP6 SWAP2 ADD TIMESTAMP LT ISZERO PUSH2 0x1537 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 DUP2 SWAP1 MSTORE PUSH1 0x40 SWAP1 DUP2 SWAP1 KECCAK256 PUSH1 0x3 DUP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND PUSH1 0x1 SWAP1 DUP2 OR SWAP1 SWAP2 SSTORE DUP2 SLOAD DUP2 DUP4 ADD SLOAD SWAP4 MLOAD PUSH1 0x2 DUP1 DUP6 ADD DUP1 SLOAD SWAP6 SWAP11 POP PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP4 AND SWAP6 SWAP5 SWAP3 SWAP4 SWAP2 SWAP3 DUP4 SWAP3 DUP6 SWAP3 PUSH1 0x0 NOT SWAP2 DUP4 AND ISZERO PUSH2 0x100 MUL SWAP2 SWAP1 SWAP2 ADD SWAP1 SWAP2 AND DIV DUP1 ISZERO PUSH2 0x15E0 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x15B5 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x15E0 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x15C3 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 GAS CALL SWAP3 POP POP POP ISZERO PUSH2 0x1619 JUMPI PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1876 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH2 0x163F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP6 SWAP1 PUSH1 0x0 DUP1 MLOAD PUSH1 0x20 PUSH2 0x1836 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE SWAP1 PUSH1 0x0 SWAP1 LOG2 PUSH1 0x3 DUP5 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP1 SSTORE JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP2 MSTORE PUSH1 0x7 PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP2 DUP3 SWAP1 KECCAK256 DUP4 SWAP1 SSTORE DUP2 MLOAD DUP4 DUP2 MSTORE SWAP2 MLOAD DUP5 SWAP3 PUSH32 0xB237AFE65F1514FD7EA3F923EA4FE792BDD07000A912B6CD1602A8E7F573C8D SWAP3 SWAP1 DUP3 SWAP1 SUB ADD SWAP1 LOG2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP2 AND ISZERO ISZERO PUSH2 0x16A9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x5 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP9 DUP2 AND DUP3 MSTORE PUSH1 0x20 DUP1 DUP4 ADD DUP10 DUP2 MSTORE DUP4 DUP6 ADD DUP10 DUP2 MSTORE PUSH1 0x0 PUSH1 0x60 DUP7 ADD DUP2 SWAP1 MSTORE DUP8 DUP2 MSTORE DUP1 DUP5 MSTORE SWAP6 SWAP1 SWAP6 KECCAK256 DUP5 MLOAD DUP2 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND SWAP5 AND SWAP4 SWAP1 SWAP4 OR DUP4 SSTORE MLOAD PUSH1 0x1 DUP4 ADD SSTORE SWAP3 MLOAD DUP1 MLOAD SWAP5 SWAP7 POP SWAP2 SWAP4 SWAP1 SWAP3 PUSH2 0x171C SWAP3 PUSH1 0x2 DUP6 ADD SWAP3 SWAP2 ADD SWAP1 PUSH2 0x179D JUMP JUMPDEST POP PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD MLOAD PUSH1 0x3 SWAP1 SWAP2 ADD DUP1 SLOAD PUSH1 0xFF NOT AND SWAP2 ISZERO ISZERO SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH1 0x5 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE PUSH1 0x40 MLOAD DUP3 SWAP1 PUSH32 0xC0BA8FE4B176C1714197D43B9CC6BCF797A4A7461C5FE8D0EF6E184AE7601E51 SWAP1 PUSH1 0x0 SWAP1 LOG2 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 GT ISZERO PUSH2 0x1798 JUMPI PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x20 SWAP1 KECCAK256 PUSH2 0x1798 SWAP2 DUP2 ADD SWAP1 DUP4 ADD PUSH2 0x181B JUMP JUMPDEST POP POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x17DE JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x180B JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x180B JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x180B JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x17F0 JUMP JUMPDEST POP PUSH2 0x1817 SWAP3 SWAP2 POP PUSH2 0x181B JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH2 0xF16 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1817 JUMPI PUSH1 0x0 DUP2 SSTORE PUSH1 0x1 ADD PUSH2 0x1821 JUMP STOP MSTORE PUSH5 0x41BB6C1ABA EXTCODECOPY SWAP11 0x4a PUSH13 0xA1D6545DA9C2333C8C48343EF3 SWAP9 0xeb DUP6 DUP14 PUSH19 0xB79236F39E6E1EB0EDCF53C221607B54B00CD2 DUP16 BALANCE SWAP7 INVALID 0xd0 LOG2 0x49 SWAP5 0xdc ADDRESS DUP12 DUP16 PUSH2 0x1B68 0x2d CALLER 0xe1 RETURNDATACOPY 0xcb SLOAD 0xc3 SMOD PUSH14 0x8E8BB8C2881800A4D972B792045F STATICCALL 0xe9 DUP16 0xdf 0x46 0xdf CALLDATASIZE 0x5f 0xed PUSH22 0x8001553A916EF2F495D26A907CC54D96ED840D7BDA71 0xe7 BALANCE SWAP5 0xbf GAS SWAP14 0xf7 0xa7 PUSH12 0x90A165627A7A723058200853 0xbb 0x25 XOR PUSH1 0xC9 0x29 GASLIMIT LOG3 0xc9 0x4e 0xbb 0xaa DUP7 0xcb 0xe3 0xf8 0xb7 0xed 0x5e SWAP6 0xb4 DUP5 DELEGATECALL 0x28 PUSH22 0x2638C133800029000000000000000000000000000000 ", - "sourceMap": - "714:2422:2:-;;;;;;;;;-1:-1:-1;;;714:2422:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2519:1:0;2507:9;:13;2503:61;;;2534:30;;;2554:9;2534:30;;;;2542:10;;2534:30;;;;;;;;;;2503:61;714:2422:2;936:23:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;936:23:0;;;;;;;;;-1:-1:-1;;;;;936:23:0;;;;;;;;;;;;;;3711:460;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3711:460:0;-1:-1:-1;;;;;3711:460:0;;;;;3196:332:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3196:332:1;;;;;890:40:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;890:40:0;-1:-1:-1;;;;;890:40:0;;;;;;;;;;;;;;;;;;;;;;;820:64;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;820:64:0;;;-1:-1:-1;;;;;820:64:0;;;;;1049:29:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1049:29:1;;;;;;;;;;;;;;;;;;;;9136:319:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;9136:319:0;;;;;;;;;;;2774:360:2;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2774:360:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2774:360:2;;-1:-1:-1;2774:360:2;;-1:-1:-1;;;;;;;2774:360:2;2058:502;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2058:502:2;;;;;3311:277:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3311:277:0;-1:-1:-1;;;;;3311:277:0;;;;;7304:337;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7304:337:0;;;;;2321:186:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2321:186:1;;;;;8622:252:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;8622:252:0;;;;;765:49;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;765:49:0;;;;;;;;;;-1:-1:-1;;;;;765:49:0;-1:-1:-1;;;;;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9539:115;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9539:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;9539:115:0;;;;;;;;;;;;;;;;;10757:676;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;10757:676:0;;;;;;;;;;;;;;;816:44:2;;8:9:-1;5:2;;;30:1;27;20:12;5:2;816:44:2;;;;9833:575:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;9833:575:0;;;;;991:28;;8:9:-1;5:2;;;30:1;27;20:12;5:2;991:28:0;;;;4990:207;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4990:207:0;;;;;2613:459:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2613:459:1;;;;;5456:244:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;5456:244:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5456:244:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5456:244:0;;-1:-1:-1;5456:244:0;;-1:-1:-1;;;;;;;5456:244:0;1085:47:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;1085:47:1;;;;;217:41:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;217:41:0;;;;965:20;;8:9:-1;5:2;;;30:1;27;20:12;5:2;965:20:0;;;;4370:449;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4370:449:0;-1:-1:-1;;;;;4370:449:0;;;;;;;;;;3642:472:1;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3642:472:1;;;;;936:23:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;936:23:0;;-1:-1:-1;936:23:0;:::o;3711:460::-;3859:6;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;-1:-1:-1;;;;;1420:14:0;;;;;;:7;:14;;;;;;3801:5;;1420:14;;1419:15;1415:38;;;1448:5;;;1415:38;-1:-1:-1;;;;;3822:14:0;;3839:5;3822:14;;;:7;:14;;;;;:22;;-1:-1:-1;;3822:22:0;;;3839:5;-1:-1:-1;3854:170:0;3871:6;:13;-1:-1:-1;;3871:17:0;3869:19;;3854:170;;;3924:5;-1:-1:-1;;;;;3911:18:0;:6;3918:1;3911:9;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3911:9:0;:18;3907:117;;;3961:6;3968:13;;-1:-1:-1;;3968:17:0;;;3961:25;;;;;;;;;;;;;;;;3949:6;:9;;-1:-1:-1;;;;;3961:25:0;;;;3956:1;;3949:9;;;;;;;;;;;;;;:37;;;;;-1:-1:-1;;;;;3949:37:0;;;;;-1:-1:-1;;;;;3949:37:0;;;;;;4004:5;;3907:117;3890:3;;;;;3854:170;;;4033:6;:18;;-1:-1:-1;;4033:18:0;;;;;;:::i;:::-;-1:-1:-1;4076:6:0;:13;4065:8;;:24;4061:74;;;4121:6;:13;4103:32;;:17;:32::i;:::-;4145:19;;-1:-1:-1;;;;;4145:19:0;;;-1:-1:-1;;;;;;;;;;;4145:19:0;;;;1242:1;3711:460;;:::o;3196:332:1:-;3279:10;1420:14:0;;;;:7;:14;;;;;;;;1419:15;1415:38;;;1448:5;;;1415:38;1694:28;;;;:13;:28;;;;;;;;3324:10:1;1694:35:0;;;;;;;;;3309:13:1;;3324:10;1694:35:0;;1693:36;1689:59;;;1743:5;;;1689:59;1976:12;:27;;;;;;;;;;:36;;;3356:13:1;;1976:36:0;;1972:59;;;2026:5;;;1972:59;3397:13:1;1205:26;1217:13;1205:11;:26::i;:::-;1204:27;1196:36;;;;;;3469:5;3426:28;;;:13;:28;;;;;;;;3455:10;3426:40;;;;;;;;:48;;-1:-1:-1;;3426:48:1;;;3484:37;3440:13;;3484:37;;;2041:1:0;1758;1463;;3196:332:1;;:::o;890:40:0:-;;;;;;;;;;;;;;;:::o;820:64::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1049:29:1:-;;;;:::o;9136:319:0:-;9243:10;;9269:179;9286:16;;9284:1;:18;9269:179;;;9328:7;:36;;;;-1:-1:-1;9340:12:0;:15;;;;;;;;;;:24;;;;;9339:25;9328:36;:92;;;;9384:8;:36;;;;-1:-1:-1;9396:12:0;:15;;;;;;;;;;:24;;;;;9384:36;9321:127;;;9447:1;9438:10;;;;9321:127;9304:3;;9269:179;;;9136:319;;;;;:::o;2774:360:2:-;2947:40;;;;;;;;;;;;;;;;2878:4;;;2998:109;3019:1;3015;:5;2998:109;;;3060:32;3093:1;3060:35;;;;;;;;-1:-1:-1;;;3060:35:2;-1:-1:-1;;;;;3049:46:2;;:4;3054:1;3049:7;;;;;;;;;;;;;;;-1:-1:-1;;;3049:7:2;;;;;-1:-1:-1;;;;;;3049:46:2;;3041:55;;;;;;3022:3;;2998:109;;;3123:4;3116:11;;2774:360;;;;;;:::o;2058:502::-;2274:22;1976:27:0;;;;;;;;;;:36;;;2153:13:2;;1976:36:0;;1972:59;;;2026:5;;;1972:59;2191:13:2;1318:26:1;1330:13;1318:11;:26::i;:::-;1310:35;;;;;;;;937:22:2;962:27;;;;;;;;;;1025:29;;1007:14;;2245:13;;962:27;-1:-1:-1;;;;;1007:14:2;;;1025:29;;1007:47;999:56;;;;;;1107:7;;;;1073:42;;;;;;;;;;;;-1:-1:-1;;1073:42:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1107:7;1073:42;;1107:7;1073:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:33;:42::i;:::-;1065:51;;;;;;;;2299:12;:27;;;;;;;;;;;;2336:11;;;:18;;-1:-1:-1;;2336:18:2;2350:4;2336:18;;;;;;2368:14;;2394:8;;;;2368:44;;2404:7;;;;2368:44;;2299:27;;-1:-1:-1;;;;;;2368:14:2;;;;2394:8;2404:7;;2368:44;;;;2404:7;;-1:-1:-1;;2368:44:2;;;;2336:18;2368:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2364:190;;;2426:24;;2436:13;;-1:-1:-1;;;;;;;;;;;2426:24:2;;;;2364:190;;;2479:31;;2496:13;;-1:-1:-1;;;;;;;;;;;2479:31:2;;;;2524:11;;;:19;;-1:-1:-1;;2524:19:2;;;2364:190;1355:1:1;;2041::0;2058:502:2;;;:::o;3311:277:0:-;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;-1:-1:-1;;;;;1312:14:0;;;;;;:7;:14;;;;;;3404:5;;1312:14;;1308:37;;;1340:5;;;1308:37;3427:5;-1:-1:-1;;;;;2104:13:0;;;2100:36;;;2131:5;;;2100:36;3459:6;:13;;;;3475:1;3459:17;3478:8;;256:2;2236:10;:28;:66;;;;2292:10;2280:9;:22;2236:66;:96;;;-1:-1:-1;2318:14:0;;2236:96;:127;;;-1:-1:-1;2348:15:0;;2236:127;2229:153;;;2377:5;;;2229:153;-1:-1:-1;;;;;3502:14:0;;;;;;:7;:14;;;;;;:21;;-1:-1:-1;;3502:21:0;3519:4;3502:21;;;;;;3533:6;27:10:-1;;23:18;;;45:23;;3533:18:0;;;;;;-1:-1:-1;;;;;;3533:18:0;;;;;3561:20;-1:-1:-1;;;;;;;;;;;3561:20:0;3502:14;3561:20;2146:1;;1355;1242;3311:277;:::o;7304:337::-;7394:4;;;7438:197;7455:6;:13;7453:15;;7438:197;;;7493:28;;;;:13;:28;;;;;7522:6;:9;;7493:28;;;7529:1;;7522:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7522:9:0;7493:39;;;;;;;;;;;;;;;7489:71;;;7559:1;7550:10;;;;7489:71;7587:8;;7578:5;:17;7574:50;;;7620:4;7613:11;;;;7574:50;7470:3;;7438:197;;2321:186:1;1186:10:0;1208:4;1186:27;1182:50;;1227:5;;;1182:50;2418:17:1;:38;;;2466:34;;;;;;;;;;;;;;;;;2321:186;:::o;8622:252:0:-;8721:10;;8747:120;8764:6;:13;8762:15;;8747:120;;;8800:28;;;;:13;:28;;;;;8829:6;:9;;8800:28;;;8836:1;;8829:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8829:9:0;8800:39;;;;;;;;;;;;;;;8796:71;;;8866:1;8857:10;;;;8796:71;8779:3;;8747:120;;;8622:252;;;;:::o;765:49::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;765:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;765:49:0;;;;;;;-1:-1:-1;;765:49:0;;;:::o;9539:115::-;9609:9;9641:6;9634:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;9634:13:0;;;;;;;;;;;;;;;;;;;;;;;9539:115;;:::o;10757:676::-;10882:22;10920:32;10993:10;11017:6;10966:16;;10955:28;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10955:28:0;;10920:63;;11006:1;10993:14;;11040:1;11038:3;;11033:250;11045:16;;11043:1;:18;11033:250;;;11087:7;:36;;;;-1:-1:-1;11099:12:0;:15;;;;;;;;;;:24;;;;;11098:25;11087:36;:92;;;;11143:8;:36;;;;-1:-1:-1;11155:12:0;:15;;;;;;;;;;:24;;;;;11143:36;11080:203;;;11239:1;11211:18;11230:5;11211:25;;;;;;;;;;;;;;;;;;:29;11267:1;11258:10;;;;;11080:203;11063:3;;11033:250;;;11326:4;11321:2;:9;11310:21;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;11310:21:0;;11292:39;;11348:4;11346:6;;11341:85;11356:2;11354:1;:4;11341:85;;;11405:18;11424:1;11405:21;;;;;;;;;;;;;;;;;;11377:15;11397:4;11393:1;:8;11377:25;;;;;;;;;;;;;;;;;;:49;11360:3;;11341:85;;;10757:676;;;;;;;;;:::o;816:44:2:-;;;-1:-1:-1;;;;;816:44:2;;:::o;9833:575:0:-;9928:24;9968:34;10043:10;10067:6;10019;:13;;;;10005:28;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10005:28:0;;9968:65;;10056:1;10043:14;;10090:1;10088:3;;10083:186;10095:6;:13;10093:15;;10083:186;;;10131:28;;;;:13;:28;;;;;10160:6;:9;;10131:28;;;10167:1;;10160:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10160:9:0;10131:39;;;;;;;;;;;;;;;10127:142;;;10217:6;:9;;10224:1;;10217:9;;;;;;;;;;;;;;;;10190:24;;-1:-1:-1;;;;;10217:9:0;;;;10190:17;;10208:5;;10190:24;;;;;;-1:-1:-1;;;;;10190:36:0;;;:24;;;;;;;;;;:36;10253:1;10244:10;;;;;10127:142;10110:3;;10083:186;;;10309:5;10295:20;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10295:20:0;;10278:37;;10332:1;10330:3;;10325:76;10337:5;10335:1;:7;10325:76;;;10381:17;10399:1;10381:20;;;;;;;;;;;;;;;;;;10361:14;10376:1;10361:17;;;;;;;;;;-1:-1:-1;;;;;10361:40:0;;;:17;;;;;;;;;;:40;10344:3;;10325:76;;;9833:575;;;;;;:::o;991:28::-;;;;:::o;4990:207::-;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;5092:6;:13;5107:9;256:2;2236:28;;;:66;;;2292:10;2280:9;:22;2236:66;:96;;;-1:-1:-1;2318:14:0;;2236:96;:127;;;-1:-1:-1;2348:15:0;;2236:127;2229:153;;;2377:5;;;2229:153;5132:8;:20;;;5162:28;;;;;;;;;;;;;;;;;1242:1;;4990:207;:::o;2613:459:1:-;2696:10;1420:14:0;;;;:7;:14;;;;;;;;1419:15;1415:38;;;1448:5;;;1415:38;1538:12;:27;;;;;;;;;;:39;2734:13:1;;-1:-1:-1;;;;;1538:39:0;:44;1534:67;;;1596:5;;;1534:67;1843:28;;;;:13;:28;;;;;;;;2785:10:1;1843:35:0;;;;;;;;;2770:13:1;;2785:10;1843:35:0;;1839:58;;;1892:5;;;1839:58;2823:13:1;1205:26;1217:13;1205:11;:26::i;:::-;1204:27;1196:36;;;;;;2852:28;;;;2895:4;2852:28;;;;;;;;2881:10;2852:40;;;;;;;;:47;;-1:-1:-1;;2852:47:1;;;;;;;2909:39;;2866:13;;2909:39;;;2962:26;2974:13;2962:11;:26::i;:::-;2958:108;;;3004:51;3024:13;3039:15;3004:19;:51::i;5456:244:0:-;5560:18;5610:40;5625:11;5638:5;5645:4;5610:14;:40::i;:::-;5594:56;;5660:33;5679:13;5660:18;:33::i;:::-;5456:244;;;;;:::o;1085:47:1:-;;;;;;;;;;;;;:::o;217:41:0:-;256:2;217:41;:::o;965:20::-;;;;:::o;4370:449::-;4541:6;1186:10;1208:4;1186:27;1182:50;;1227:5;;;1182:50;-1:-1:-1;;;;;1420:14:0;;;;;;:7;:14;;;;;;4479:5;;1420:14;;1419:15;1415:38;;;1448:5;;;1415:38;-1:-1:-1;;;;;1312:14:0;;;;;;:7;:14;;;;;;4512:8;;1312:14;;1308:37;;;1340:5;;;1308:37;4548:1;4541:8;;4536:149;4553:6;:13;4551:15;;4536:149;;;4602:5;-1:-1:-1;;;;;4589:18:0;:6;4596:1;4589:9;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4589:9:0;:18;4585:100;;;4639:8;4627:6;4634:1;4627:9;;;;;;;;;;;;;;;;;;:20;;;;;-1:-1:-1;;;;;4627:20:0;;;;;-1:-1:-1;;;;;4627:20:0;;;;;;4665:5;;4585:100;4568:3;;;;;4536:149;;;-1:-1:-1;;;;;4694:14:0;;;4711:5;4694:14;;;:7;:14;;;;;;:22;;-1:-1:-1;;4694:22:0;;;;;;4726:17;;;;;;;;:24;;;;;4694:22;4726:24;;;;4760:19;;4694:14;;-1:-1:-1;;;;;;;;;;;4760:19:0;;4789:23;;-1:-1:-1;;;;;4789:23:0;;;-1:-1:-1;;;;;;;;;;;4789:23:0;;;;1463:1;1242;4370:449;;;:::o;3642:472:1:-;3828:22;1976:27:0;;;;;;;;;;:36;;;3725:13:1;;1976:36:0;;1972:59;;;2026:5;;;1972:59;3763:13:1;1318:26;1330:13;1318:11;:26::i;:::-;1310:35;;;;;;;;1483:17;;1448:32;;;;:17;:32;;;;;;3799:13;;1448:52;1429:15;:71;;1421:80;;;;;;3853:12;:27;;;;;;;;;;;;3890:11;;;:18;;-1:-1:-1;;3890:18:1;3904:4;3890:18;;;;;;3922:14;;3948:8;;;;3922:44;;3958:7;;;;3922:44;;3853:27;;-1:-1:-1;;;;;;3922:14:1;;;;3948:8;3958:7;;3922:44;;;;3958:7;;-1:-1:-1;;3922:44:1;;;;3890:18;3922:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3918:190;;;3980:24;;3990:13;;-1:-1:-1;;;;;;;;;;;3980:24:1;;;;3918:190;;;4033:31;;4050:13;;-1:-1:-1;;;;;;;;;;;4033:31:1;;;;4078:11;;;:19;;-1:-1:-1;;4078:19:1;;;3918:190;1355:1;2041::0;3642:472:1;;;:::o;4224:223::-;4327:32;;;;:17;:32;;;;;;;;;:51;;;4388:52;;;;;;;4345:13;;4388:52;;;;;;;;;4224:223;;:::o;7974:451:0:-;8106:18;8076:11;-1:-1:-1;;;;;2104:13:0;;;2100:36;;;2131:5;;;2100:36;8156:16;;8212:140;;;;;;;;-1:-1:-1;;;;;8212:140:0;;;;;;;;;;;;;;;;;;-1:-1:-1;8212:140:0;;;;;;8182:27;;;;;;;;;;:170;;;;-1:-1:-1;;;;;;8182:170:0;;;;;;;;;;-1:-1:-1;8182:170:0;;;;;;;8156:16;;-1:-1:-1;8212:140:0;;8182:27;;:170;;;;;;;;;;:::i;:::-;-1:-1:-1;8182:170:0;;;;;;;;;;;;-1:-1:-1;;8182:170:0;;;;;;;;;;8362:16;:21;;-1:-1:-1;8362:21:0;;;8393:25;;8404:13;;8393:25;;-1:-1:-1;;8393:25:0;7974:451;;;;;;:::o;714:2422:2:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;714:2422:2;;;-1:-1:-1;714:2422:2;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;" - } - } - }, - "sources": { - "current/multisig/MultiSigWallet/MultiSigWallet.sol": { - "id": 0 - }, - "current/multisig/MultiSigWalletWithTimeLock/MultiSigWalletWithTimeLock.sol": { - "id": 1 - }, - "current/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol": { - "id": 2 - } - }, - "sourceCodes": { - "current/multisig/MultiSigWallet/MultiSigWallet.sol": - "pragma solidity ^0.4.10;\n\n/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.\n/// @author Stefan George - \ncontract MultiSigWallet {\n\n uint constant public MAX_OWNER_COUNT = 50;\n\n event Confirmation(address indexed sender, uint indexed transactionId);\n event Revocation(address indexed sender, uint indexed transactionId);\n event Submission(uint indexed transactionId);\n event Execution(uint indexed transactionId);\n event ExecutionFailure(uint indexed transactionId);\n event Deposit(address indexed sender, uint value);\n event OwnerAddition(address indexed owner);\n event OwnerRemoval(address indexed owner);\n event RequirementChange(uint required);\n\n mapping (uint => Transaction) public transactions;\n mapping (uint => mapping (address => bool)) public confirmations;\n mapping (address => bool) public isOwner;\n address[] public owners;\n uint public required;\n uint public transactionCount;\n\n struct Transaction {\n address destination;\n uint value;\n bytes data;\n bool executed;\n }\n\n modifier onlyWallet() {\n if (msg.sender != address(this))\n throw;\n _;\n }\n\n modifier ownerDoesNotExist(address owner) {\n if (isOwner[owner])\n throw;\n _;\n }\n\n modifier ownerExists(address owner) {\n if (!isOwner[owner])\n throw;\n _;\n }\n\n modifier transactionExists(uint transactionId) {\n if (transactions[transactionId].destination == 0)\n throw;\n _;\n }\n\n modifier confirmed(uint transactionId, address owner) {\n if (!confirmations[transactionId][owner])\n throw;\n _;\n }\n\n modifier notConfirmed(uint transactionId, address owner) {\n if (confirmations[transactionId][owner])\n throw;\n _;\n }\n\n modifier notExecuted(uint transactionId) {\n if (transactions[transactionId].executed)\n throw;\n _;\n }\n\n modifier notNull(address _address) {\n if (_address == 0)\n throw;\n _;\n }\n\n modifier validRequirement(uint ownerCount, uint _required) {\n if ( ownerCount > MAX_OWNER_COUNT\n || _required > ownerCount\n || _required == 0\n || ownerCount == 0)\n throw;\n _;\n }\n\n /// @dev Fallback function allows to deposit ether.\n function()\n payable\n {\n if (msg.value > 0)\n Deposit(msg.sender, msg.value);\n }\n\n /*\n * Public functions\n */\n /// @dev Contract constructor sets initial owners and required number of confirmations.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n function MultiSigWallet(address[] _owners, uint _required)\n public\n validRequirement(_owners.length, _required)\n {\n for (uint i=0; i<_owners.length; i++) {\n if (isOwner[_owners[i]] || _owners[i] == 0)\n throw;\n isOwner[_owners[i]] = true;\n }\n owners = _owners;\n required = _required;\n }\n\n /// @dev Allows to add a new owner. Transaction has to be sent by wallet.\n /// @param owner Address of new owner.\n function addOwner(address owner)\n public\n onlyWallet\n ownerDoesNotExist(owner)\n notNull(owner)\n validRequirement(owners.length + 1, required)\n {\n isOwner[owner] = true;\n owners.push(owner);\n OwnerAddition(owner);\n }\n\n /// @dev Allows to remove an owner. Transaction has to be sent by wallet.\n /// @param owner Address of owner.\n function removeOwner(address owner)\n public\n onlyWallet\n ownerExists(owner)\n {\n isOwner[owner] = false;\n for (uint i=0; i owners.length)\n changeRequirement(owners.length);\n OwnerRemoval(owner);\n }\n\n /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.\n /// @param owner Address of owner to be replaced.\n /// @param owner Address of new owner.\n function replaceOwner(address owner, address newOwner)\n public\n onlyWallet\n ownerExists(owner)\n ownerDoesNotExist(newOwner)\n {\n for (uint i=0; i\ncontract MultiSigWalletWithTimeLock is MultiSigWallet {\n\n event ConfirmationTimeSet(uint indexed transactionId, uint confirmationTime);\n event TimeLockChange(uint secondsTimeLocked);\n\n uint public secondsTimeLocked;\n\n mapping (uint => uint) public confirmationTimes;\n\n modifier notFullyConfirmed(uint transactionId) {\n require(!isConfirmed(transactionId));\n _;\n }\n\n modifier fullyConfirmed(uint transactionId) {\n require(isConfirmed(transactionId));\n _;\n }\n\n modifier pastTimeLock(uint transactionId) {\n require(block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked);\n _;\n }\n\n /*\n * Public functions\n */\n\n /// @dev Contract constructor sets initial owners, required number of confirmations, and time lock.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.\n function MultiSigWalletWithTimeLock(address[] _owners, uint _required, uint _secondsTimeLocked)\n public\n MultiSigWallet(_owners, _required)\n {\n secondsTimeLocked = _secondsTimeLocked;\n }\n\n /// @dev Changes the duration of the time lock for transactions.\n /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.\n function changeTimeLock(uint _secondsTimeLocked)\n public\n onlyWallet\n {\n secondsTimeLocked = _secondsTimeLocked;\n TimeLockChange(_secondsTimeLocked);\n }\n\n /// @dev Allows an owner to confirm a transaction.\n /// @param transactionId Transaction ID.\n function confirmTransaction(uint transactionId)\n public\n ownerExists(msg.sender)\n transactionExists(transactionId)\n notConfirmed(transactionId, msg.sender)\n notFullyConfirmed(transactionId)\n {\n confirmations[transactionId][msg.sender] = true;\n Confirmation(msg.sender, transactionId);\n if (isConfirmed(transactionId)) {\n setConfirmationTime(transactionId, block.timestamp);\n }\n }\n\n /// @dev Allows an owner to revoke a confirmation for a transaction.\n /// @param transactionId Transaction ID.\n function revokeConfirmation(uint transactionId)\n public\n ownerExists(msg.sender)\n confirmed(transactionId, msg.sender)\n notExecuted(transactionId)\n notFullyConfirmed(transactionId)\n {\n confirmations[transactionId][msg.sender] = false;\n Revocation(msg.sender, transactionId);\n }\n\n /// @dev Allows anyone to execute a confirmed transaction.\n /// @param transactionId Transaction ID.\n function executeTransaction(uint transactionId)\n public\n notExecuted(transactionId)\n fullyConfirmed(transactionId)\n pastTimeLock(transactionId)\n {\n Transaction storage tx = transactions[transactionId];\n tx.executed = true;\n if (tx.destination.call.value(tx.value)(tx.data))\n Execution(transactionId);\n else {\n ExecutionFailure(transactionId);\n tx.executed = false;\n }\n }\n\n /*\n * Internal functions\n */\n\n /// @dev Sets the time of when a submission first passed.\n function setConfirmationTime(uint transactionId, uint confirmationTime)\n internal\n {\n confirmationTimes[transactionId] = confirmationTime;\n ConfirmationTimeSet(transactionId, confirmationTime);\n }\n}\n", - "current/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol": - "/*\n\n Copyright 2018 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 solidity ^0.4.10;\n\nimport { MultiSigWalletWithTimeLock } from \"../MultiSigWalletWithTimeLock/MultiSigWalletWithTimeLock.sol\";\n\ncontract MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress is MultiSigWalletWithTimeLock {\n\n address public TOKEN_TRANSFER_PROXY_CONTRACT;\n\n modifier validRemoveAuthorizedAddressTx(uint transactionId) {\n Transaction storage tx = transactions[transactionId];\n require(tx.destination == TOKEN_TRANSFER_PROXY_CONTRACT);\n require(isFunctionRemoveAuthorizedAddress(tx.data));\n _;\n }\n\n /// @dev Contract constructor sets initial owners, required number of confirmations, time lock, and tokenTransferProxy address.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.\n /// @param _tokenTransferProxy Address of TokenTransferProxy contract.\n function MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress(\n address[] _owners,\n uint _required,\n uint _secondsTimeLocked,\n address _tokenTransferProxy)\n public\n MultiSigWalletWithTimeLock(_owners, _required, _secondsTimeLocked)\n {\n TOKEN_TRANSFER_PROXY_CONTRACT = _tokenTransferProxy;\n }\n\n /// @dev Allows execution of removeAuthorizedAddress without time lock.\n /// @param transactionId Transaction ID.\n function executeRemoveAuthorizedAddress(uint transactionId)\n public\n notExecuted(transactionId)\n fullyConfirmed(transactionId)\n validRemoveAuthorizedAddressTx(transactionId)\n {\n Transaction storage tx = transactions[transactionId];\n tx.executed = true;\n if (tx.destination.call.value(tx.value)(tx.data))\n Execution(transactionId);\n else {\n ExecutionFailure(transactionId);\n tx.executed = false;\n }\n }\n\n /// @dev Compares first 4 bytes of byte array to removeAuthorizedAddress function signature.\n /// @param data Transaction data.\n /// @return Successful if data is a call to removeAuthorizedAddress.\n function isFunctionRemoveAuthorizedAddress(bytes data)\n public\n constant\n returns (bool)\n {\n bytes4 removeAuthorizedAddressSignature = bytes4(sha3(\"removeAuthorizedAddress(address)\"));\n for (uint i = 0; i < 4; i++) {\n require(data[i] == removeAuthorizedAddressSignature[i]);\n }\n return true;\n }\n}\n" - }, - "sourceTreeHashHex": "0xdac022bb4f4cd50563fb21da8efb584e698d76b401d3c823cf757a1a2da3aea0", - "compiler": { - "name": "solc", - "version": "0.4.24", - "settings": { - "optimizer": { - "enabled": true, - "runs": 0 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode.object", - "evm.bytecode.sourceMap", - "evm.deployedBytecode.object", - "evm.deployedBytecode.sourceMap" - ] - } - } - } - }, - "networks": {} -} ->>>>>>> aa338761... updated migrations artifacts +} \ No newline at end of file -- cgit v1.2.3 From 0d4ff5a916694be7cb5772bbd7d3e610522e09df Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Jun 2018 13:56:10 -0700 Subject: Updated tests to use new revert handler --- packages/contracts/test/asset_proxy/proxies.ts | 4 ++-- packages/contracts/test/libraries/lib_bytes.ts | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index 0548a2aac..ea236ab24 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -341,7 +341,7 @@ describe('Asset Transfer Proxies', () => { // Perform a transfer from makerAddress to takerAddress const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); - return expect( + return expectRevertOrAlwaysFailingTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync( encodedAssetData, makerAddress, @@ -349,7 +349,7 @@ describe('Asset Transfer Proxies', () => { amount, { from: exchangeAddress }, ), - ).to.be.rejectedWith(constants.REVERT); + ); }); it('should throw if transferring 0 amount of a token', async () => { diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 5830c5753..e0d214ea2 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -385,27 +385,27 @@ describe('LibBytes', () => { it('should fail if the byte array is too short to hold the length of a nested byte array)', async () => { // The length of the nested array is 32 bytes. By storing less than 32 bytes, a length cannot be read. const offset = new BigNumber(0); - return expect(libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( - constants.REVERT, + return expectRevertOrAlwaysFailingTransactionAsync( + libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, offset), ); }); it('should fail if we store a nested byte array length, without a nested byte array)', async () => { const offset = new BigNumber(0); - return expect(libBytes.publicReadBytes.callAsync(testBytes32, offset)).to.be.rejectedWith(constants.REVERT); + return expectRevertOrAlwaysFailingTransactionAsync(libBytes.publicReadBytes.callAsync(testBytes32, offset)); }); it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength); - return expect( + return expectRevertOrAlwaysFailingTransactionAsync( libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, badOffset), - ).to.be.rejectedWith(constants.REVERT); + ); }); it('should fail if the length between the offset and end of the byte array is too short to hold the nested byte array)', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); - return expect(libBytes.publicReadBytes.callAsync(testBytes32, badOffset)).to.be.rejectedWith( - constants.REVERT, + return expectRevertOrAlwaysFailingTransactionAsync( + libBytes.publicReadBytes.callAsync(testBytes32, badOffset), ); }); }); @@ -489,16 +489,16 @@ describe('LibBytes', () => { it('should fail if the byte array is too short to hold the length of a nested byte array)', async () => { const offset = new BigNumber(0); const emptyByteArray = ethUtil.bufferToHex(new Buffer(1)); - return expect(libBytes.publicWriteBytes.callAsync(emptyByteArray, offset, longData)).to.be.rejectedWith( - constants.REVERT, + return expectRevertOrAlwaysFailingTransactionAsync( + libBytes.publicWriteBytes.callAsync(emptyByteArray, offset, longData), ); }); it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => { const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength)); const badOffset = new BigNumber(ethUtil.toBuffer(shortTestBytesAsBuffer).byteLength); - return expect(libBytes.publicWriteBytes.callAsync(emptyByteArray, badOffset, shortData)).to.be.rejectedWith( - constants.REVERT, + return expectRevertOrAlwaysFailingTransactionAsync( + libBytes.publicWriteBytes.callAsync(emptyByteArray, badOffset, shortData), ); }); }); -- cgit v1.2.3 From d62ff34a5a5794a586c0b4bbf27c51ea36efd659 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Jun 2018 15:53:30 -0700 Subject: Cleanup after last rebase --- packages/contracts/test/asset_proxy/decoder.ts | 2 +- packages/contracts/test/asset_proxy/proxies.ts | 4 ++-- packages/contracts/test/libraries/lib_bytes.ts | 3 +-- packages/contracts/test/libraries/lib_mem.ts | 2 +- packages/order-utils/src/order_state_utils.ts | 4 ++-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 16486f4fd..41ea91648 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -7,7 +7,7 @@ import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); import * as Web3 from 'web3'; -import { TestAssetDataDecodersContract } from '../../src/contract_wrappers/generated/test_asset_data_decoders'; +import { TestAssetDataDecodersContract } from '../../src/generated_contract_wrappers/test_asset_data_decoders'; import { artifacts } from '../../src/utils/artifacts'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index ea236ab24..50040092e 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -7,11 +7,11 @@ import { LogWithDecodedArgs } from 'ethereum-types'; import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; +import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC721ReceiverContract, TokenReceivedContractEventArgs, -} from '../../src/contract_wrappers/generated/dummy_e_r_c721_receiver'; -import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; +} from '../../src/generated_contract_wrappers/dummy_e_r_c721_receiver'; import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token'; import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy'; import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy'; diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index e0d214ea2..8334d856b 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -8,8 +8,7 @@ import ethUtil = require('ethereumjs-util'); import { TestLibBytesContract } from '../../src/generated_contract_wrappers/test_lib_bytes'; import { artifacts } from '../../src/utils/artifacts'; -import { expectRevertOrOtherErrorAsync, expectRevertOrOtherErrorAsync } from '../../src/utils/assertions'; -import { assetProxyUtils } from '../../src/utils/asset_proxy_utils'; +import { expectRevertOrAlwaysFailingTransactionAsync, expectRevertOrOtherErrorAsync } from '../../src/utils/assertions'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 6291d3d08..8682a36a4 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -1,7 +1,7 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; -import { TestLibMemContract } from '../../src/contract_wrappers/generated/test_lib_mem'; +import { TestLibMemContract } from '../../src/generated_contract_wrappers/test_lib_mem'; import { artifacts } from '../../src/utils/artifacts'; import { chaiSetup } from '../../src/utils/chai_setup'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index 12f5d8f7e..40f235da7 100644 --- a/packages/order-utils/src/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -79,7 +79,7 @@ export class OrderStateUtils { } public async getOrderRelevantStateAsync(signedOrder: SignedOrder): Promise { const zrxTokenAddress = this._orderFilledCancelledFetcher.getZRXTokenAddress(); - const makerProxyData = assetProxyUtils.decodeERC20ProxyData(signedOrder.makerAssetData); + const makerProxyData = assetProxyUtils.decodeERC20AssetData(signedOrder.makerAssetData); const makerAssetAddress = makerProxyData.tokenAddress; const orderHash = orderHashUtils.getOrderHashHex(signedOrder); const makerBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync( @@ -112,7 +112,7 @@ export class OrderStateUtils { const transferrableFeeAssetAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]); const zrxAssetData = assetProxyUtils.encodeERC20AssetData(zrxTokenAddress); - const isMakerTokenZRX = signedOrder.makerAssetData === zrxAssetData; + const isMakerAssetZRX = signedOrder.makerAssetData === zrxAssetData; const remainingFillableCalculator = new RemainingFillableCalculator( signedOrder.makerFee, signedOrder.makerAssetAmount, -- cgit v1.2.3 From 05123ea6f48a71ac0a53dcadcbc5924cbd1d1486 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Jun 2018 16:32:42 -0700 Subject: Updated LibBytes error messages --- .../contracts/current/utils/LibBytes/LibBytes.sol | 2 +- packages/contracts/src/utils/constants.ts | 10 ++--- packages/contracts/test/libraries/lib_bytes.ts | 52 +++++++++++++--------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 4f9e2f152..d1d10476f 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -26,7 +26,7 @@ contract LibBytes is // Revert reasons string constant GREATER_THAN_ZERO_LENGTH_REQUIRED = "GREATER_THAN_ZERO_LENGTH_REQUIRED"; - string constant GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED = "GREATER_THAN_4_LENGTH_REQUIRED"; + string constant GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED"; string constant GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED"; string constant GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED"; string constant GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED"; diff --git a/packages/contracts/src/utils/constants.ts b/packages/contracts/src/utils/constants.ts index fa2a4af3c..af3f26d82 100644 --- a/packages/contracts/src/utils/constants.ts +++ b/packages/contracts/src/utils/constants.ts @@ -19,11 +19,11 @@ const TESTRPC_PRIVATE_KEYS_STRINGS = [ export const constants = { INVALID_OPCODE: 'invalid opcode', REVERT: 'revert', - LIB_BYTES_GT_ZERO_LENGTH_REQUIRED: 'Length must be greater than 0.', - LIB_BYTES_GTE_4_LENGTH_REQUIRED: 'Length must be greater than or equal to 4.', - LIB_BYTES_GTE_20_LENGTH_REQUIRED: 'Length must be greater than or equal to 20.', - LIB_BYTES_GTE_32_LENGTH_REQUIRED: 'Length must be greater than or equal to 32.', - LIB_BYTES_INDEX_OUT_OF_BOUNDS: 'Specified array index is out of bounds.', + LIB_BYTES_GREATER_THAN_ZERO_LENGTH_REQUIRED: 'GREATER_THAN_ZERO_LENGTH_REQUIRED', + LIB_BYTES_GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED', + LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED', + LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED', + LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED', ERC20_INSUFFICIENT_BALANCE: 'Insufficient balance to complete transfer.', ERC20_INSUFFICIENT_ALLOWANCE: 'Insufficient allowance to complete transfer.', TESTRPC_NETWORK_ID: 50, diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 8334d856b..a3da5baac 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -91,7 +91,7 @@ describe('LibBytes', () => { it('should revert if length is 0', async () => { return expectRevertOrOtherErrorAsync( libBytes.publicPopByte.callAsync(constants.NULL_BYTES), - constants.LIB_BYTES_GT_ZERO_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_THAN_ZERO_LENGTH_REQUIRED, ); }); @@ -108,7 +108,7 @@ describe('LibBytes', () => { it('should revert if length is less than 20', async () => { return expectRevertOrOtherErrorAsync( libBytes.publicPopAddress.callAsync(byteArrayShorterThan20Bytes), - constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED, ); }); @@ -194,7 +194,7 @@ describe('LibBytes', () => { const offset = new BigNumber(0); return expectRevertOrOtherErrorAsync( libBytes.publicReadAddress.callAsync(shortByteArray, offset), - constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED, ); }); @@ -203,7 +203,7 @@ describe('LibBytes', () => { const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength); return expectRevertOrOtherErrorAsync( libBytes.publicReadAddress.callAsync(byteArray, badOffset), - constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED, ); }); }); @@ -240,7 +240,7 @@ describe('LibBytes', () => { const offset = new BigNumber(0); return expectRevertOrOtherErrorAsync( libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset), - constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED, ); }); @@ -248,7 +248,7 @@ describe('LibBytes', () => { const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); return expectRevertOrOtherErrorAsync( libBytes.publicReadBytes32.callAsync(testBytes32, badOffset), - constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED, ); }); }); @@ -289,7 +289,7 @@ describe('LibBytes', () => { const offset = new BigNumber(0); return expectRevertOrOtherErrorAsync( libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset), - constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED, ); }); @@ -300,7 +300,7 @@ describe('LibBytes', () => { const badOffset = new BigNumber(testUint256AsBuffer.byteLength); return expectRevertOrOtherErrorAsync( libBytes.publicReadUint256.callAsync(byteArray, badOffset), - constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED, ); }); }); @@ -322,7 +322,7 @@ describe('LibBytes', () => { const byteArrayLessThan4Bytes = '0x010101'; return expectRevertOrOtherErrorAsync( libBytes.publicReadFirst4.callAsync(byteArrayLessThan4Bytes), - constants.LIB_BYTES_GTE_4_LENGTH_REQUIRED, + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED, ); }); it('should return the first 4 bytes of a byte array of arbitrary length', async () => { @@ -381,30 +381,36 @@ describe('LibBytes', () => { return expect(bytes).to.be.equal(longData); }); - it('should fail if the byte array is too short to hold the length of a nested byte array)', async () => { + it('should fail if the byte array is too short to hold the length of a nested byte array', async () => { // The length of the nested array is 32 bytes. By storing less than 32 bytes, a length cannot be read. const offset = new BigNumber(0); - return expectRevertOrAlwaysFailingTransactionAsync( + return expectRevertOrOtherErrorAsync( libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, offset), + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED, ); }); - it('should fail if we store a nested byte array length, without a nested byte array)', async () => { + it('should fail if we store a nested byte array length, without a nested byte array', async () => { const offset = new BigNumber(0); - return expectRevertOrAlwaysFailingTransactionAsync(libBytes.publicReadBytes.callAsync(testBytes32, offset)); + return expectRevertOrOtherErrorAsync( + libBytes.publicReadBytes.callAsync(testBytes32, offset), + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED, + ); }); - it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => { + it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength); - return expectRevertOrAlwaysFailingTransactionAsync( + return expectRevertOrOtherErrorAsync( libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, badOffset), + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED, ); }); - it('should fail if the length between the offset and end of the byte array is too short to hold the nested byte array)', async () => { + it('should fail if the length between the offset and end of the byte array is too short to hold the nested byte array', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); - return expectRevertOrAlwaysFailingTransactionAsync( + return expectRevertOrOtherErrorAsync( libBytes.publicReadBytes.callAsync(testBytes32, badOffset), + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED, ); }); }); @@ -435,7 +441,7 @@ describe('LibBytes', () => { return expect(bytes).to.be.equal(shortData); }); - it('should successfully write a nested array of bytes - one word in length - when it takes up the whole array)', async () => { + it('should successfully write a nested array of bytes - one word in length - when it takes up the whole array', async () => { const testBytesOffset = new BigNumber(0); const emptyByteArray = ethUtil.bufferToHex(new Buffer(wordOfTestBytesAsBuffer.byteLength)); const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, wordOfData); @@ -460,7 +466,7 @@ describe('LibBytes', () => { return expect(bytes).to.be.equal(wordOfData); }); - it('should successfully write a long, nested bytes when it takes up the whole array)', async () => { + it('should successfully write a long, nested bytes when it takes up the whole array', async () => { const testBytesOffset = new BigNumber(0); const emptyByteArray = ethUtil.bufferToHex(new Buffer(longTestBytesAsBuffer.byteLength)); const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, longData); @@ -485,19 +491,21 @@ describe('LibBytes', () => { return expect(bytes).to.be.equal(longData); }); - it('should fail if the byte array is too short to hold the length of a nested byte array)', async () => { + it('should fail if the byte array is too short to hold the length of a nested byte array', async () => { const offset = new BigNumber(0); const emptyByteArray = ethUtil.bufferToHex(new Buffer(1)); - return expectRevertOrAlwaysFailingTransactionAsync( + return expectRevertOrOtherErrorAsync( libBytes.publicWriteBytes.callAsync(emptyByteArray, offset, longData), + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED, ); }); it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => { const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength)); const badOffset = new BigNumber(ethUtil.toBuffer(shortTestBytesAsBuffer).byteLength); - return expectRevertOrAlwaysFailingTransactionAsync( + return expectRevertOrOtherErrorAsync( libBytes.publicWriteBytes.callAsync(emptyByteArray, badOffset, shortData), + constants.LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED, ); }); }); -- cgit v1.2.3 From c39301b6da9f51ebccf11f06865c439ffed7f8f6 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 8 Jun 2018 11:04:07 -0700 Subject: Fixed assetProxyUtils for linter --- packages/order-utils/src/asset_proxy_utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_proxy_utils.ts index ee5fff1d2..915ee5032 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_proxy_utils.ts @@ -109,7 +109,7 @@ export const assetProxyUtils = { ERC721_ASSET_DATA_TOKEN_ID_OFFSET, ); const proxyIdOffset = encodedAssetData.byteLength - 1; - const encodedAssetProxyId = encodedAssetData.slice(-1); + const encodedAssetProxyId = encodedAssetData.slice(proxyIdOffset); const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); if (assetProxyId !== AssetProxyId.ERC721) { throw new Error( @@ -141,7 +141,7 @@ export const assetProxyUtils = { } const encodedReceiverData = encodedAssetData.slice( ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET, - ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET + receiverDataLength.toNumber(), + receiverDataLength.add(ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET).toNumber(), ); receiverData = ethUtil.bufferToHex(encodedReceiverData); } -- cgit v1.2.3 From 05fbc8e6b061e5cef5bb8b8078176f9b375c2ec5 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 8 Jun 2018 11:43:47 -0700 Subject: Linter changes to contracts --- packages/contracts/test/asset_proxy/decoder.ts | 8 +------- packages/contracts/test/asset_proxy/proxies.ts | 6 ++---- packages/contracts/test/libraries/lib_bytes.ts | 7 ++----- packages/contracts/test/libraries/lib_mem.ts | 6 +----- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts index 41ea91648..d4fae1601 100644 --- a/packages/contracts/test/asset_proxy/decoder.ts +++ b/packages/contracts/test/asset_proxy/decoder.ts @@ -1,16 +1,12 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; -import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); -import * as Web3 from 'web3'; import { TestAssetDataDecodersContract } from '../../src/generated_contract_wrappers/test_asset_data_decoders'; import { artifacts } from '../../src/utils/artifacts'; import { chaiSetup } from '../../src/utils/chai_setup'; -import { constants } from '../../src/utils/constants'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); @@ -18,7 +14,6 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('TestAssetDataDecoders', () => { - let owner: string; let testAssetProxyDecoder: TestAssetDataDecodersContract; let testAddress: string; @@ -31,8 +26,7 @@ describe('TestAssetDataDecoders', () => { before(async () => { // Setup accounts & addresses const accounts = await web3Wrapper.getAvailableAddressesAsync(); - owner = accounts[0]; - testAddress = accounts[1]; + testAddress = accounts[0]; // Deploy TestLibMem testAssetProxyDecoder = await TestAssetDataDecodersContract.deployFrom0xArtifactAsync( artifacts.TestAssetDataDecoders, diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index 50040092e..08376ccfb 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -1,6 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; -import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import { LogWithDecodedArgs } from 'ethereum-types'; @@ -28,6 +27,7 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +// tslint:disable:no-unnecessary-type-assertion describe('Asset Transfer Proxies', () => { let owner: string; let notAuthorized: string; @@ -271,7 +271,6 @@ describe('Asset Transfer Proxies', () => { const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress - const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); const txHash = await erc721Proxy.transferFrom.sendTransactionAsync( encodedAssetData, @@ -303,7 +302,6 @@ describe('Asset Transfer Proxies', () => { const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress - const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); const txHash = await erc721Proxy.transferFrom.sendTransactionAsync( encodedAssetData, @@ -339,7 +337,6 @@ describe('Asset Transfer Proxies', () => { const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress - const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(1); return expectRevertOrAlwaysFailingTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync( @@ -486,3 +483,4 @@ describe('Asset Transfer Proxies', () => { }); }); }); +// tslint:enable:no-unnecessary-type-assertion diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index a3da5baac..2fefb7aeb 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -1,6 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; -import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import BN = require('bn.js'); import * as chai from 'chai'; @@ -8,7 +7,7 @@ import ethUtil = require('ethereumjs-util'); import { TestLibBytesContract } from '../../src/generated_contract_wrappers/test_lib_bytes'; import { artifacts } from '../../src/utils/artifacts'; -import { expectRevertOrAlwaysFailingTransactionAsync, expectRevertOrOtherErrorAsync } from '../../src/utils/assertions'; +import { expectRevertOrOtherErrorAsync } from '../../src/utils/assertions'; import { chaiSetup } from '../../src/utils/chai_setup'; import { constants } from '../../src/utils/constants'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; @@ -341,7 +340,6 @@ describe('LibBytes', () => { it('should successfully read short, nested array of bytes when it is offset in the array', async () => { const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); - const shortDataAsBuffer = ethUtil.toBuffer(shortData); const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, shortTestBytesAsBuffer]); const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); @@ -357,7 +355,6 @@ describe('LibBytes', () => { it('should successfully read a nested array of bytes - one word in length - when it is offset in the array', async () => { const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); - const wordOfDataAsBuffer = ethUtil.toBuffer(wordOfData); const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, wordOfTestBytesAsBuffer]); const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); @@ -373,7 +370,6 @@ describe('LibBytes', () => { it('should successfully read long, nested array of bytes when it is offset in the array', async () => { const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); - const longDataAsBuffer = ethUtil.toBuffer(longData); const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, longTestBytesAsBuffer]); const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); @@ -510,3 +506,4 @@ describe('LibBytes', () => { }); }); }); +// tslint:disable:max-file-line-count diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 8682a36a4..90d54edcb 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -4,7 +4,7 @@ import * as chai from 'chai'; import { TestLibMemContract } from '../../src/generated_contract_wrappers/test_lib_mem'; import { artifacts } from '../../src/utils/artifacts'; import { chaiSetup } from '../../src/utils/chai_setup'; -import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; +import { provider, txDefaults } from '../../src/utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -16,13 +16,9 @@ const toHex = (buf: Uint8Array): string => buf.reduce((a, v) => a + ('00' + v.to const fromHex = (str: string): Uint8Array => Uint8Array.from(Buffer.from(str.slice(2), 'hex')); describe('LibMem', () => { - let owner: string; let testLibMem: TestLibMemContract; before(async () => { - // Setup accounts & addresses - const accounts = await web3Wrapper.getAvailableAddressesAsync(); - owner = accounts[0]; // Deploy TestLibMem testLibMem = await TestLibMemContract.deployFrom0xArtifactAsync(artifacts.TestLibMem, provider, txDefaults); }); -- cgit v1.2.3