{
  "address": "0x4b1EE84A72b44B78346e069D1c66509940827E22",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "_root",
          "type": "bytes32"
        },
        {
          "internalType": "bytes",
          "name": "_key",
          "type": "bytes"
        },
        {
          "internalType": "bytes[]",
          "name": "_proof",
          "type": "bytes[]"
        },
        {
          "internalType": "bytes",
          "name": "_node",
          "type": "bytes"
        }
      ],
      "name": "verifyTrieProof",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "pure",
      "type": "function"
    }
  ],
  "transactionHash": "0x73f4f0ebe4816e07d0f72cee0fc2daf55638d890ff4692bee3c235576b267a66",
  "receipt": {
    "to": null,
    "from": "0xA8caef9AcC2244a1505e7bDdE84578102A8C7f41",
    "contractAddress": "0x4b1EE84A72b44B78346e069D1c66509940827E22",
    "transactionIndex": 0,
    "gasUsed": "914467",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x286c7fd5aad2cd81825b1fe8631fb550aabc8c2c8e25e09b764496f7e6ac5426",
    "transactionHash": "0x73f4f0ebe4816e07d0f72cee0fc2daf55638d890ff4692bee3c235576b267a66",
    "logs": [],
    "blockNumber": 6785597,
    "cumulativeGasUsed": "914467",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "29f5e44d5d5914748f5336e51c2bcd06",
  "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_key\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"_proof\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"_node\",\"type\":\"bytes\"}],\"name\":\"verifyTrieProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MPTVerify.sol\":\"MPTVerify\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/MPTVerify.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.7;\\n\\nimport \\\"./interface/IMPTVerify.sol\\\";\\nimport \\\"./lib/MPT.sol\\\";\\ncontract MPTVerify is IMPTVerify {\\n    function verifyTrieProof(\\n        bytes32 _root,\\n        bytes memory _key,\\n        bytes[] memory _proof,\\n        bytes memory _node\\n    ) external pure override returns (bool) {\\n        return MPT.verify(_node,_key,_proof,_root);\\n    }\\n}\\n\",\"keccak256\":\"0x5e612c052083ecfefb2ee5354c0feddfd3405004cbb51fff65892c450c58cf54\",\"license\":\"MIT\"},\"contracts/interface/IMPTVerify.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n\\ninterface IMPTVerify {\\n    function verifyTrieProof(\\n        bytes32 _root,\\n        bytes memory _key,\\n        bytes[] memory _proof,\\n        bytes memory _node\\n    ) external pure returns (bool);\\n}\\n\",\"keccak256\":\"0x2441a69e46e9208036ee6bc3d17f99651a9b80ce46af46a3d9106e3a34ee3425\",\"license\":\"MIT\"},\"contracts/lib/MPT.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/*\\n * @title MerklePatriciaVerifier\\n * @author Sam Mayo (sammayo888@gmail.com)\\n *\\n * @dev Library for verifing merkle patricia proofs.\\n */\\n\\npragma solidity ^0.8.0;\\n\\nimport {RLPReader} from \\\"./RLPReader.sol\\\";\\n\\n\\nlibrary MPT {\\n    /*\\n   * @dev Verifies a merkle patricia proof.\\n   * @param value The terminating value in the trie.\\n   * @param encodedPath The path in the trie leading to value.\\n   * @param rlpParentNodes The rlp encoded stack of nodes.\\n   * @param root The root hash of the trie.\\n   * @return The boolean validity of the proof.\\n   */\\n    function verify(\\n        bytes memory value,\\n        bytes memory encodedPath,\\n        bytes[] memory rlpParentNodes,\\n        bytes32 root\\n    ) internal pure returns (bool) {\\n      //  RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes);\\n      //  RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item);\\n\\n        bytes memory currentNode;\\n        RLPReader.RLPItem[] memory currentNodeList;\\n\\n        bytes32 nodeKey = root;\\n        uint256 pathPtr = 0;\\n        bytes memory path = encodedPath;//_getNibbleArray(encodedPath);\\n        if (path.length == 0) {\\n            return false;\\n        }\\n\\n        for (uint256 i = 0; i < rlpParentNodes.length; i++) {\\n            if (pathPtr > path.length) {\\n                return false;\\n            }\\n\\n            currentNode = rlpParentNodes[i];\\n            if (nodeKey != keccak256(currentNode)) {\\n                return false;\\n            }\\n            currentNodeList = RLPReader.toList(RLPReader.toRlpItem(rlpParentNodes[i]));\\n\\n            if (currentNodeList.length == 17) {\\n                if (pathPtr == path.length) {\\n                    if (\\n                        keccak256(RLPReader.toBytes(currentNodeList[16])) ==\\n                        keccak256(value)\\n                    ) {\\n                        return true;\\n                    } else {\\n                        return false;\\n                    }\\n                }\\n\\n                uint8 nextPathNibble = uint8(path[pathPtr]);\\n                if (nextPathNibble > 16) {\\n                    return false;\\n                }\\n                nodeKey = bytes32(\\n                    RLPReader.toUintStrict(currentNodeList[nextPathNibble])\\n                );\\n                pathPtr += 1;\\n            } else if (currentNodeList.length == 2) {\\n                uint256 traversed = _nibblesToTraverse(\\n                    RLPReader.toBytes(currentNodeList[0]),\\n                    path,\\n                    pathPtr\\n                );\\n                if (pathPtr + traversed == path.length) {\\n                    //leaf node\\n                    if (\\n                        keccak256(RLPReader.toBytes(currentNodeList[1])) ==\\n                        keccak256(value)\\n                    ) {\\n                        return true;\\n                    } else {\\n                        return false;\\n                    }\\n                }\\n\\n                //extension node\\n                if (traversed == 0) {\\n                    return false;\\n                }\\n\\n                pathPtr += traversed;\\n                nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1]));\\n            } else {\\n                return false;\\n            }\\n        }\\n\\n        return false;\\n    }\\n\\n    function _nibblesToTraverse(\\n        bytes memory encodedPartialPath,\\n        bytes memory path,\\n        uint256 pathPtr\\n    ) private pure returns (uint256) {\\n        uint256 len;\\n        // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath\\n        // and slicedPath have elements that are each one hex character (1 nibble)\\n        bytes memory partialPath = _getNibbleArray(encodedPartialPath);\\n        bytes memory slicedPath = new bytes(partialPath.length);\\n\\n        // pathPtr counts nibbles in path\\n        // partialPath.length is a number of nibbles\\n        for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) {\\n            bytes1 pathNibble = path[i];\\n            slicedPath[i - pathPtr] = pathNibble;\\n        }\\n\\n        if (keccak256(partialPath) == keccak256(slicedPath)) {\\n            len = partialPath.length;\\n        } else {\\n            len = 0;\\n        }\\n        return len;\\n    }\\n\\n    // bytes b must be hp encoded\\n    function _getNibbleArray(bytes memory b)\\n        private\\n        pure\\n        returns (bytes memory)\\n    {\\n        bytes memory nibbles;\\n        if (b.length > 0) {\\n            uint8 offset;\\n            uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b));\\n            if (hpNibble == 1 || hpNibble == 3) {\\n                nibbles = new bytes(b.length * 2 - 1);\\n                bytes1 oddNibble = _getNthNibbleOfBytes(1, b);\\n                nibbles[0] = oddNibble;\\n                offset = 1;\\n            } else {\\n                nibbles = new bytes(b.length * 2 - 2);\\n                offset = 0;\\n            }\\n            //console.logUint(offset);\\n            for (uint256 i = offset; i < nibbles.length; i++) {\\n                nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b);\\n            }\\n        }\\n        return nibbles;\\n    }\\n\\n    function _getNthNibbleOfBytes(uint256 n, bytes memory str)\\n        private\\n        pure\\n        returns (bytes1)\\n    {\\n        return\\n            bytes1(\\n                n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10\\n            );\\n    }\\n}\\n\",\"keccak256\":\"0xdfa97de10be5cb3ecc0ba76610ebbcbc19ab8d576b9cdb658eece8bee074f051\",\"license\":\"MIT\"},\"contracts/lib/RLPReader.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/*\\n * @author Hamdi Allam hamdi.allam97@gmail.com\\n * Please reach out with any questions or concerns\\n */\\npragma solidity ^0.8.0;\\n\\nlibrary RLPReader {\\n    uint8 constant STRING_SHORT_START = 0x80;\\n    uint8 constant STRING_LONG_START = 0xb8;\\n    uint8 constant LIST_SHORT_START = 0xc0;\\n    uint8 constant LIST_LONG_START = 0xf8;\\n    uint8 constant WORD_SIZE = 32;\\n\\n    struct RLPItem {\\n        uint256 len;\\n        uint256 memPtr;\\n    }\\n\\n    struct Iterator {\\n        RLPItem item; // Item that's being iterated over.\\n        uint256 nextPtr; // Position of the next item in the list.\\n    }\\n\\n    /*\\n     * @dev Returns the next element in the iteration. Reverts if it has not next element.\\n     * @param self The iterator.\\n     * @return The next element in the iteration.\\n     */\\n    function next(Iterator memory self) internal pure returns (RLPItem memory) {\\n        require(hasNext(self), \\\"not have next\\\");\\n\\n        uint256 ptr = self.nextPtr;\\n        uint256 itemLength = _itemLength(ptr);\\n        self.nextPtr = ptr + itemLength;\\n\\n        return RLPItem(itemLength, ptr);\\n    }\\n\\n    /*\\n     * @dev Returns true if the iteration has more elements.\\n     * @param self The iterator.\\n     * @return true if the iteration has more elements.\\n     */\\n    function hasNext(Iterator memory self) internal pure returns (bool) {\\n        RLPItem memory item = self.item;\\n        return self.nextPtr < item.memPtr + item.len;\\n    }\\n\\n    /*\\n     * @param item RLP encoded bytes\\n     */\\n    function toRlpItem(bytes memory item)\\n    internal\\n    pure\\n    returns (RLPItem memory)\\n    {\\n        uint256 memPtr;\\n        assembly {\\n            memPtr := add(item, 0x20)\\n        }\\n\\n        return RLPItem(item.length, memPtr);\\n    }\\n\\n    /*\\n     * @dev Create an iterator. Reverts if item is not a list.\\n     * @param self The RLP item.\\n     * @return An 'Iterator' over the item.\\n     */\\n    function iterator(RLPItem memory self)\\n    internal\\n    pure\\n    returns (Iterator memory)\\n    {\\n        require(isList(self), \\\"check self list fail\\\");\\n\\n        uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);\\n        return Iterator(self, ptr);\\n    }\\n\\n    /*\\n     * @param the RLP item.\\n     */\\n    function rlpLen(RLPItem memory item) internal pure returns (uint256) {\\n        return item.len;\\n    }\\n\\n    /*\\n     * @param the RLP item.\\n     * @return (memPtr, len) pair: location of the item's payload in memory.\\n     */\\n    function payloadLocation(RLPItem memory item)\\n    internal\\n    pure\\n    returns (uint256, uint256)\\n    {\\n        uint256 offset = _payloadOffset(item.memPtr);\\n        uint256 memPtr = item.memPtr + offset;\\n        uint256 len = item.len - offset;\\n        // data length\\n        return (memPtr, len);\\n    }\\n\\n    /*\\n     * @param the RLP item.\\n     */\\n    function payloadLen(RLPItem memory item) internal pure returns (uint256) {\\n        (, uint256 len) = payloadLocation(item);\\n        return len;\\n    }\\n\\n    /*\\n     * @param the RLP item containing the encoded list.\\n     */\\n    function toList(RLPItem memory item)\\n    internal\\n    pure\\n    returns (RLPItem[] memory)\\n    {\\n        require(isList(item), \\\"is list fail\\\");\\n\\n        uint256 items = numItems(item);\\n        RLPItem[] memory result = new RLPItem[](items);\\n\\n        uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);\\n        uint256 dataLen;\\n        for (uint256 i = 0; i < items; i++) {\\n            dataLen = _itemLength(memPtr);\\n            result[i] = RLPItem(dataLen, memPtr);\\n            memPtr = memPtr + dataLen;\\n        }\\n\\n        return result;\\n    }\\n\\n    // @return indicator whether encoded payload is a list. negate this function call for isData.\\n    function isList(RLPItem memory item) internal pure returns (bool) {\\n        if (item.len == 0) return false;\\n\\n        uint8 byte0;\\n        uint256 memPtr = item.memPtr;\\n        assembly {\\n            byte0 := byte(0, mload(memPtr))\\n        }\\n\\n        if (byte0 < LIST_SHORT_START) return false;\\n        return true;\\n    }\\n\\n    /*\\n     * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory.\\n     * @return keccak256 hash of RLP encoded bytes.\\n     */\\n    function rlpBytesKeccak256(RLPItem memory item)\\n    internal\\n    pure\\n    returns (bytes32)\\n    {\\n        uint256 ptr = item.memPtr;\\n        uint256 len = item.len;\\n        bytes32 result;\\n        assembly {\\n            result := keccak256(ptr, len)\\n        }\\n        return result;\\n    }\\n\\n    /*\\n     * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory.\\n     * @return keccak256 hash of the item payload.\\n     */\\n    function payloadKeccak256(RLPItem memory item)\\n    internal\\n    pure\\n    returns (bytes32)\\n    {\\n        (uint256 memPtr, uint256 len) = payloadLocation(item);\\n        bytes32 result;\\n        assembly {\\n            result := keccak256(memPtr, len)\\n        }\\n        return result;\\n    }\\n\\n    /** RLPItem conversions into data types **/\\n\\n    // @returns raw rlp encoding in bytes\\n    function toRlpBytes(RLPItem memory item)\\n    internal\\n    pure\\n    returns (bytes memory)\\n    {\\n        bytes memory result = new bytes(item.len);\\n        if (result.length == 0) return result;\\n\\n        uint256 ptr;\\n        assembly {\\n            ptr := add(0x20, result)\\n        }\\n\\n        copy(item.memPtr, ptr, item.len);\\n        return result;\\n    }\\n\\n    // any non-zero byte except \\\"0x80\\\" is considered true\\n    function toBoolean(RLPItem memory item) internal pure returns (bool) {\\n        require(item.len == 1, \\\"item len is not one\\\");\\n        uint256 result;\\n        uint256 memPtr = item.memPtr;\\n        assembly {\\n            result := byte(0, mload(memPtr))\\n        }\\n\\n        // SEE Github Issue #5.\\n        // Summary: Most commonly used RLP libraries (i.e Geth) will encode\\n        // \\\"0\\\" as \\\"0x80\\\" instead of as \\\"0\\\". We handle this edge case explicitly\\n        // here.\\n        if (result == 0 || result == STRING_SHORT_START) {\\n            return false;\\n        } else {\\n            return true;\\n        }\\n    }\\n\\n    function toAddress(RLPItem memory item) internal pure returns (address) {\\n        // 1 byte for the length prefix\\n        require(item.len == 21, \\\"item len is not 21\\\");\\n\\n        return address(uint160(toUint(item)));\\n    }\\n\\n    function toUint(RLPItem memory item) internal pure returns (uint256) {\\n        require(item.len > 0 && item.len <= 33, \\\"item len is not uint\\\");\\n\\n        (uint256 memPtr, uint256 len) = payloadLocation(item);\\n\\n        uint256 result;\\n        assembly {\\n            result := mload(memPtr)\\n\\n        // shfit to the correct location if neccesary\\n            if lt(len, 32) {\\n                result := div(result, exp(256, sub(32, len)))\\n            }\\n        }\\n\\n        return result;\\n    }\\n\\n    // enforces 32 byte length\\n    function toUintStrict(RLPItem memory item) internal pure returns (uint256) {\\n        // one byte prefix\\n        require(item.len == 33, \\\"item is not uint strict\\\");\\n\\n        uint256 result;\\n        uint256 memPtr = item.memPtr + 1;\\n        assembly {\\n            result := mload(memPtr)\\n        }\\n\\n        return result;\\n    }\\n\\n    function toBytes(RLPItem memory item) internal pure returns (bytes memory) {\\n        require(item.len > 0, \\\"item len is zero\\\");\\n\\n        (uint256 memPtr, uint256 len) = payloadLocation(item);\\n        bytes memory result = new bytes(len);\\n\\n        uint256 destPtr;\\n        assembly {\\n            destPtr := add(0x20, result)\\n        }\\n\\n        copy(memPtr, destPtr, len);\\n        return result;\\n    }\\n\\n    /*\\n     * Private Helpers\\n     */\\n\\n    // @return number of payload items inside an encoded list.\\n    function numItems(RLPItem memory item) internal pure returns (uint256) {\\n        if (item.len == 0) return 0;\\n\\n        uint256 count = 0;\\n        uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);\\n        uint256 endPtr = item.memPtr + item.len;\\n        while (currPtr < endPtr) {\\n            currPtr = currPtr + _itemLength(currPtr);\\n            // skip over an item\\n            count++;\\n        }\\n\\n        return count;\\n    }\\n\\n    // @return entire rlp item byte length\\n    function _itemLength(uint256 memPtr) private pure returns (uint256) {\\n        uint256 itemLen;\\n        uint256 byte0;\\n        assembly {\\n            byte0 := byte(0, mload(memPtr))\\n        }\\n\\n        if (byte0 < STRING_SHORT_START) itemLen = 1;\\n        else if (byte0 < STRING_LONG_START)\\n            itemLen = byte0 - STRING_SHORT_START + 1;\\n        else if (byte0 < LIST_SHORT_START) {\\n            assembly {\\n                let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is\\n                memPtr := add(memPtr, 1) // skip over the first byte\\n\\n            /* 32 byte word size */\\n                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len\\n                itemLen := add(dataLen, add(byteLen, 1))\\n            }\\n        } else if (byte0 < LIST_LONG_START) {\\n            itemLen = byte0 - LIST_SHORT_START + 1;\\n        } else {\\n            assembly {\\n                let byteLen := sub(byte0, 0xf7)\\n                memPtr := add(memPtr, 1)\\n\\n                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length\\n                itemLen := add(dataLen, add(byteLen, 1))\\n            }\\n        }\\n\\n        return itemLen;\\n    }\\n\\n    // @return number of bytes until the data\\n    function _payloadOffset(uint256 memPtr) private pure returns (uint256) {\\n        uint256 byte0;\\n        assembly {\\n            byte0 := byte(0, mload(memPtr))\\n        }\\n\\n        if (byte0 < STRING_SHORT_START) return 0;\\n        else if (\\n            byte0 < STRING_LONG_START ||\\n            (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)\\n        ) return 1;\\n        else if (byte0 < LIST_SHORT_START)\\n        // being explicit\\n            return byte0 - (STRING_LONG_START - 1) + 1;\\n        else return byte0 - (LIST_LONG_START - 1) + 1;\\n    }\\n\\n    /*\\n     * @param src Pointer to source\\n     * @param dest Pointer to destination\\n     * @param len Amount of memory to copy from the source\\n     */\\n    function copy(\\n        uint256 src,\\n        uint256 dest,\\n        uint256 len\\n    ) private pure {\\n        if (len == 0) return;\\n\\n        // copy as many word sizes as possible\\n        for (; len >= WORD_SIZE; len -= WORD_SIZE) {\\n            assembly {\\n                mstore(dest, mload(src))\\n            }\\n\\n            src += WORD_SIZE;\\n            dest += WORD_SIZE;\\n        }\\n\\n        if (len > 0) {\\n            // left over bytes. Mask is used to remove unwanted bytes from the word\\n            uint256 mask = 256 ** (WORD_SIZE - len) - 1;\\n            assembly {\\n                let srcpart := and(mload(src), not(mask)) // zero out src\\n                let destpart := and(mload(dest), mask) // retrieve the bytes\\n                mstore(dest, or(destpart, srcpart))\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x39b810b4e66f244a397c1231c11adaa6de6615bb44e0bb22ef1b068fa6ba66ca\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b50610f96806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c58b5b6214610030575b600080fd5b61004361003e366004610bd9565b610057565b604051901515815260200160405180910390f35b600061006582858588610070565b90505b949350505050565b8251600090606090819084908490889061009257600095505050505050610068565b60005b88518110156102fb5781518311156100b65760009650505050505050610068565b8881815181106100c8576100c8610f34565b60200260200101519550858051906020012084146100ef5760009650505050505050610068565b61014161013c8a838151811061010757610107610f34565b602002602001015160408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61030c565b945084516011141561021d5781518314156101ac578a805190602001206101818660108151811061017457610174610f34565b6020026020010151610459565b80519060200120141561019d5760019650505050505050610068565b60009650505050505050610068565b60008284815181106101c0576101c0610f34565b016020015160f81c905060108111156101e3576000975050505050505050610068565b610208868260ff16815181106101fb576101fb610f34565b602002602001015161050d565b9450610215600185610d25565b9350506102e9565b84516002141561019d5760006102496102428760008151811061017457610174610f34565b848661057e565b83519091506102588286610d25565b14156102a9578b8051906020012061027c8760018151811061017457610174610f34565b805190602001201415610299576001975050505050505050610068565b6000975050505050505050610068565b806102be576000975050505050505050610068565b6102c88185610d25565b93506102e0866001815181106101fb576101fb610f34565b94506102e99050565b806102f381610eb7565b915050610095565b5060009a9950505050505050505050565b606061031782610688565b6103575760405162461bcd60e51b815260206004820152600c60248201526b1a5cc81b1a5cdd0819985a5b60a21b60448201526064015b60405180910390fd5b6000610362836106c1565b905060008167ffffffffffffffff81111561037f5761037f610f4a565b6040519080825280602002602001820160405280156103c457816020015b604080518082019091526000808252602082015281526020019060019003908161039d5790505b50905060006103d68560200151610744565b85602001516103e59190610d25565b90506000805b8481101561044e576103fc836107c6565b915060405180604001604052808381526020018481525084828151811061042557610425610f34565b602090810291909101015261043a8284610d25565b92508061044681610eb7565b9150506103eb565b509195945050505050565b805160609061049d5760405162461bcd60e51b815260206004820152601060248201526f6974656d206c656e206973207a65726f60801b604482015260640161034e565b6000806104a98461086f565b9150915060008167ffffffffffffffff8111156104c8576104c8610f4a565b6040519080825280601f01601f1916602001820160405280156104f2576020820181803683370190505b509050602081016105048482856108b6565b50949350505050565b80516000906021146105615760405162461bcd60e51b815260206004820152601760248201527f6974656d206973206e6f742075696e7420737472696374000000000000000000604482015260640161034e565b600080836020015160016105759190610d25565b51949350505050565b600080600061058c86610936565b90506000815167ffffffffffffffff8111156105aa576105aa610f4a565b6040519080825280601f01601f1916602001820160405280156105d4576020820181803683370190505b509050845b82516105e59087610d25565b81101561065857600087828151811061060057610600610f34565b01602001516001600160f81b0319169050808361061d8985610e7d565b8151811061062d5761062d610f34565b60200101906001600160f81b031916908160001a90535050808061065090610eb7565b9150506105d9565b50808051906020012082805190602001201415610678578151925061067d565b600092505b509095945050505050565b805160009061069957506000919050565b6020820151805160001a9060c08210156106b7575060009392505050565b5060019392505050565b80516000906106d257506000919050565b6000806106e28460200151610744565b84602001516106f19190610d25565b90506000846000015185602001516107099190610d25565b90505b8082101561073b5761071d826107c6565b6107279083610d25565b91508261073381610eb7565b93505061070c565b50909392505050565b8051600090811a608081101561075d5750600092915050565b60b8811080610778575060c08110801590610778575060f881105b156107865750600192915050565b60c08110156107ba5761079b600160b8610e94565b6107a89060ff1682610e7d565b6107b3906001610d25565b9392505050565b61079b600160f8610e94565b80516000908190811a60808110156107e15760019150610868565b60b8811015610807576107f5608082610e7d565b610800906001610d25565b9150610868565b60c08110156108345760b78103600185019450806020036101000a85510460018201810193505050610868565b60f8811015610848576107f560c082610e7d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006108818460200151610744565b905060008185602001516108959190610d25565b905060008286600001516108a99190610e7d565b9196919550909350505050565b806108c057505050565b602081106108f857825182526108d7602084610d25565b92506108e4602083610d25565b91506108f1602082610e7d565b90506108c0565b8015610931576000600161090d836020610e7d565b61091990610100610db6565b6109239190610e7d565b845184518216911916178352505b505050565b606080600083511115610ae257600080610951600086610ae8565b60f81c9050600181148061096857508060ff166003145b15610a105760018551600261097d9190610e5e565b6109879190610e7d565b67ffffffffffffffff81111561099f5761099f610f4a565b6040519080825280601f01601f1916602001820160405280156109c9576020820181803683370190505b50925060006109d9600187610ae8565b905080846000815181106109ef576109ef610f34565b60200101906001600160f81b031916908160001a9053506001925050610a74565b600285516002610a209190610e5e565b610a2a9190610e7d565b67ffffffffffffffff811115610a4257610a42610f4a565b6040519080825280601f01601f191660200182016040528015610a6c576020820181803683370190505b509250600091505b60ff82165b8351811015610ade57610aa3610a9260ff851683610e7d565b610a9d906002610d25565b87610ae8565b848281518110610ab557610ab5610f34565b60200101906001600160f81b031916908160001a90535080610ad681610eb7565b915050610a79565b5050505b92915050565b6000610af5600284610ed2565b15610b2f57601082610b08600286610d3d565b81518110610b1857610b18610f34565b0160200151610b2a919060f81c610ee6565b610b5f565b601082610b3d600286610d3d565b81518110610b4d57610b4d610f34565b0160200151610b5f919060f81c610d51565b60f81b9392505050565b600082601f830112610b7a57600080fd5b813567ffffffffffffffff811115610b9457610b94610f4a565b610ba7601f8201601f1916602001610cf4565b818152846020838601011115610bbc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215610bef57600080fd5b8435935060208086013567ffffffffffffffff80821115610c0f57600080fd5b610c1b89838a01610b69565b95506040880135915080821115610c3157600080fd5b818801915088601f830112610c4557600080fd5b813581811115610c5757610c57610f4a565b8060051b610c66858201610cf4565b8281528581019085870183870188018e1015610c8157600080fd5b600093505b84841015610cc057803586811115610c9d57600080fd5b610cab8f8a838b0101610b69565b84525060019390930192918701918701610c86565b5097505050506060880135925080831115610cda57600080fd5b5050610ce887828801610b69565b91505092959194509250565b604051601f8201601f1916810167ffffffffffffffff81118282101715610d1d57610d1d610f4a565b604052919050565b60008219821115610d3857610d38610f08565b500190565b600082610d4c57610d4c610f1e565b500490565b600060ff831680610d6457610d64610f1e565b8060ff84160491505092915050565b600181815b80851115610dae578160001904821115610d9457610d94610f08565b80851615610da157918102915b93841c9390800290610d78565b509250929050565b60006107b38383600082610dcc57506001610ae2565b81610dd957506000610ae2565b8160018114610def5760028114610df957610e15565b6001915050610ae2565b60ff841115610e0a57610e0a610f08565b50506001821b610ae2565b5060208310610133831016604e8410600b8410161715610e38575081810a610ae2565b610e428383610d73565b8060001904821115610e5657610e56610f08565b029392505050565b6000816000190483118215151615610e7857610e78610f08565b500290565b600082821015610e8f57610e8f610f08565b500390565b600060ff821660ff841680821015610eae57610eae610f08565b90039392505050565b6000600019821415610ecb57610ecb610f08565b5060010190565b600082610ee157610ee1610f1e565b500690565b600060ff831680610ef957610ef9610f1e565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220ab3f7a57110ed98c0ac4303b15c50c47b914bc3d1aeefad06839bdc5a752975664736f6c63430008070033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c58b5b6214610030575b600080fd5b61004361003e366004610bd9565b610057565b604051901515815260200160405180910390f35b600061006582858588610070565b90505b949350505050565b8251600090606090819084908490889061009257600095505050505050610068565b60005b88518110156102fb5781518311156100b65760009650505050505050610068565b8881815181106100c8576100c8610f34565b60200260200101519550858051906020012084146100ef5760009650505050505050610068565b61014161013c8a838151811061010757610107610f34565b602002602001015160408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61030c565b945084516011141561021d5781518314156101ac578a805190602001206101818660108151811061017457610174610f34565b6020026020010151610459565b80519060200120141561019d5760019650505050505050610068565b60009650505050505050610068565b60008284815181106101c0576101c0610f34565b016020015160f81c905060108111156101e3576000975050505050505050610068565b610208868260ff16815181106101fb576101fb610f34565b602002602001015161050d565b9450610215600185610d25565b9350506102e9565b84516002141561019d5760006102496102428760008151811061017457610174610f34565b848661057e565b83519091506102588286610d25565b14156102a9578b8051906020012061027c8760018151811061017457610174610f34565b805190602001201415610299576001975050505050505050610068565b6000975050505050505050610068565b806102be576000975050505050505050610068565b6102c88185610d25565b93506102e0866001815181106101fb576101fb610f34565b94506102e99050565b806102f381610eb7565b915050610095565b5060009a9950505050505050505050565b606061031782610688565b6103575760405162461bcd60e51b815260206004820152600c60248201526b1a5cc81b1a5cdd0819985a5b60a21b60448201526064015b60405180910390fd5b6000610362836106c1565b905060008167ffffffffffffffff81111561037f5761037f610f4a565b6040519080825280602002602001820160405280156103c457816020015b604080518082019091526000808252602082015281526020019060019003908161039d5790505b50905060006103d68560200151610744565b85602001516103e59190610d25565b90506000805b8481101561044e576103fc836107c6565b915060405180604001604052808381526020018481525084828151811061042557610425610f34565b602090810291909101015261043a8284610d25565b92508061044681610eb7565b9150506103eb565b509195945050505050565b805160609061049d5760405162461bcd60e51b815260206004820152601060248201526f6974656d206c656e206973207a65726f60801b604482015260640161034e565b6000806104a98461086f565b9150915060008167ffffffffffffffff8111156104c8576104c8610f4a565b6040519080825280601f01601f1916602001820160405280156104f2576020820181803683370190505b509050602081016105048482856108b6565b50949350505050565b80516000906021146105615760405162461bcd60e51b815260206004820152601760248201527f6974656d206973206e6f742075696e7420737472696374000000000000000000604482015260640161034e565b600080836020015160016105759190610d25565b51949350505050565b600080600061058c86610936565b90506000815167ffffffffffffffff8111156105aa576105aa610f4a565b6040519080825280601f01601f1916602001820160405280156105d4576020820181803683370190505b509050845b82516105e59087610d25565b81101561065857600087828151811061060057610600610f34565b01602001516001600160f81b0319169050808361061d8985610e7d565b8151811061062d5761062d610f34565b60200101906001600160f81b031916908160001a90535050808061065090610eb7565b9150506105d9565b50808051906020012082805190602001201415610678578151925061067d565b600092505b509095945050505050565b805160009061069957506000919050565b6020820151805160001a9060c08210156106b7575060009392505050565b5060019392505050565b80516000906106d257506000919050565b6000806106e28460200151610744565b84602001516106f19190610d25565b90506000846000015185602001516107099190610d25565b90505b8082101561073b5761071d826107c6565b6107279083610d25565b91508261073381610eb7565b93505061070c565b50909392505050565b8051600090811a608081101561075d5750600092915050565b60b8811080610778575060c08110801590610778575060f881105b156107865750600192915050565b60c08110156107ba5761079b600160b8610e94565b6107a89060ff1682610e7d565b6107b3906001610d25565b9392505050565b61079b600160f8610e94565b80516000908190811a60808110156107e15760019150610868565b60b8811015610807576107f5608082610e7d565b610800906001610d25565b9150610868565b60c08110156108345760b78103600185019450806020036101000a85510460018201810193505050610868565b60f8811015610848576107f560c082610e7d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006108818460200151610744565b905060008185602001516108959190610d25565b905060008286600001516108a99190610e7d565b9196919550909350505050565b806108c057505050565b602081106108f857825182526108d7602084610d25565b92506108e4602083610d25565b91506108f1602082610e7d565b90506108c0565b8015610931576000600161090d836020610e7d565b61091990610100610db6565b6109239190610e7d565b845184518216911916178352505b505050565b606080600083511115610ae257600080610951600086610ae8565b60f81c9050600181148061096857508060ff166003145b15610a105760018551600261097d9190610e5e565b6109879190610e7d565b67ffffffffffffffff81111561099f5761099f610f4a565b6040519080825280601f01601f1916602001820160405280156109c9576020820181803683370190505b50925060006109d9600187610ae8565b905080846000815181106109ef576109ef610f34565b60200101906001600160f81b031916908160001a9053506001925050610a74565b600285516002610a209190610e5e565b610a2a9190610e7d565b67ffffffffffffffff811115610a4257610a42610f4a565b6040519080825280601f01601f191660200182016040528015610a6c576020820181803683370190505b509250600091505b60ff82165b8351811015610ade57610aa3610a9260ff851683610e7d565b610a9d906002610d25565b87610ae8565b848281518110610ab557610ab5610f34565b60200101906001600160f81b031916908160001a90535080610ad681610eb7565b915050610a79565b5050505b92915050565b6000610af5600284610ed2565b15610b2f57601082610b08600286610d3d565b81518110610b1857610b18610f34565b0160200151610b2a919060f81c610ee6565b610b5f565b601082610b3d600286610d3d565b81518110610b4d57610b4d610f34565b0160200151610b5f919060f81c610d51565b60f81b9392505050565b600082601f830112610b7a57600080fd5b813567ffffffffffffffff811115610b9457610b94610f4a565b610ba7601f8201601f1916602001610cf4565b818152846020838601011115610bbc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215610bef57600080fd5b8435935060208086013567ffffffffffffffff80821115610c0f57600080fd5b610c1b89838a01610b69565b95506040880135915080821115610c3157600080fd5b818801915088601f830112610c4557600080fd5b813581811115610c5757610c57610f4a565b8060051b610c66858201610cf4565b8281528581019085870183870188018e1015610c8157600080fd5b600093505b84841015610cc057803586811115610c9d57600080fd5b610cab8f8a838b0101610b69565b84525060019390930192918701918701610c86565b5097505050506060880135925080831115610cda57600080fd5b5050610ce887828801610b69565b91505092959194509250565b604051601f8201601f1916810167ffffffffffffffff81118282101715610d1d57610d1d610f4a565b604052919050565b60008219821115610d3857610d38610f08565b500190565b600082610d4c57610d4c610f1e565b500490565b600060ff831680610d6457610d64610f1e565b8060ff84160491505092915050565b600181815b80851115610dae578160001904821115610d9457610d94610f08565b80851615610da157918102915b93841c9390800290610d78565b509250929050565b60006107b38383600082610dcc57506001610ae2565b81610dd957506000610ae2565b8160018114610def5760028114610df957610e15565b6001915050610ae2565b60ff841115610e0a57610e0a610f08565b50506001821b610ae2565b5060208310610133831016604e8410600b8410161715610e38575081810a610ae2565b610e428383610d73565b8060001904821115610e5657610e56610f08565b029392505050565b6000816000190483118215151615610e7857610e78610f08565b500290565b600082821015610e8f57610e8f610f08565b500390565b600060ff821660ff841680821015610eae57610eae610f08565b90039392505050565b6000600019821415610ecb57610ecb610f08565b5060010190565b600082610ee157610ee1610f1e565b500690565b600060ff831680610ef957610ef9610f1e565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220ab3f7a57110ed98c0ac4303b15c50c47b914bc3d1aeefad06839bdc5a752975664736f6c63430008070033",
  "devdoc": {
    "kind": "dev",
    "methods": {},
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [],
    "types": null
  }
}