{
  "address": "0x1d8368eAe8414e27501a3840F67bD6e640069510",
  "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": "0x38a9b88af18481b851807fcfcb82cbb76d69819c9c703b67f81e01e26fa3a6dc",
  "receipt": {
    "to": null,
    "from": "0x038BCF8d2d48C084B661E3f2B3c514b4244B4D90",
    "contractAddress": "0x1d8368eAe8414e27501a3840F67bD6e640069510",
    "transactionIndex": 0,
    "gasUsed": "919454",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x71b169a5b9a424761d72cdd2ed0d8ebae7a7944750d88cfb922d9293fc516f46",
    "transactionHash": "0x38a9b88af18481b851807fcfcb82cbb76d69819c9c703b67f81e01e26fa3a6dc",
    "logs": [],
    "blockNumber": 11627030,
    "cumulativeGasUsed": "919454",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "c98a8b06712c91abe01ddbae68094b6f",
  "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\\\";\\n\\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\":\"0xa7683b124d6c74b71ad10c0b00742daccfd7a3c173c3d983eafe065d7d4c488e\",\"license\":\"MIT\"},\"contracts/interface/IMPTVerify.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\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\":\"0xd8783438e8299828d6e650cd47e140b6cdd26cea5a40bcbc9e4d2dc5ec3cc9ba\",\"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\\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 (keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value)) {\\n                    if (RLPReader.payloadKeccak256(currentNodeList[16]) == keccak256(value)) {\\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(RLPReader.toUintStrict(currentNodeList[nextPathNibble]));\\n                pathPtr += 1;\\n            } else if (currentNodeList.length == 2) {\\n                uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr);\\n                if (pathPtr + traversed == path.length) {\\n                    //leaf node\\n                    //if (keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value)) {\\n                    if (RLPReader.payloadKeccak256(currentNodeList[1]) == keccak256(value)) {\\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) private pure returns (bytes memory) {\\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) private pure returns (bytes1) {\\n        return bytes1(n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10);\\n    }\\n}\\n\",\"keccak256\":\"0xc383b42d2fa8e81ff10b5a0e0f34ab3a3142ce8fe5bcac65d4d956ea4f00cdae\",\"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) internal pure returns (RLPItem memory) {\\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) internal pure returns (Iterator memory) {\\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) internal pure returns (uint256, uint256) {\\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) internal pure returns (RLPItem[] memory) {\\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    /*\\n     * @param get the RLP item by index. save gas.\\n     */\\n    function getItemByIndex(RLPItem memory item, uint idx) internal pure returns (RLPItem memory) {\\n        require(isList(item), \\\"is list fail\\\");\\n\\n        uint memPtr = item.memPtr + _payloadOffset(item.memPtr);\\n        uint dataLen;\\n        for (uint i = 0; i < idx; i++) {\\n            dataLen = _itemLength(memPtr);\\n            memPtr = memPtr + dataLen;\\n        }\\n        dataLen = _itemLength(memPtr);\\n        return RLPItem(dataLen, memPtr);\\n    }\\n\\n    /*\\n     * @param get the RLP item by index. save gas.\\n     */\\n    function safeGetItemByIndex(RLPItem memory item, uint idx) internal pure returns (RLPItem memory) {\\n        require(isList(item), \\\"is list fail\\\");\\n\\n        uint endPtr = item.memPtr + item.len;\\n\\n        uint memPtr = item.memPtr + _payloadOffset(item.memPtr);\\n        uint dataLen;\\n        for (uint i = 0; i < idx; i++) {\\n            dataLen = _itemLength(memPtr);\\n            memPtr = memPtr + dataLen;\\n        }\\n        dataLen = _itemLength(memPtr);\\n\\n        require(memPtr + dataLen <= endPtr, \\\"RLP item overflow\\\");\\n        return RLPItem(dataLen, memPtr);\\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) internal pure returns (bytes32) {\\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) internal pure returns (bytes32) {\\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) internal pure returns (bytes memory) {\\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    function toBytes32(RLPItem memory item) internal pure returns (bytes32) {\\n        // one byte prefix\\n        require(item.len == 33, \\\"item is not bytes32\\\");\\n\\n        bytes32 result;\\n        uint256 memPtr = item.memPtr + 1;\\n        assembly {\\n            result := mload(memPtr)\\n        }\\n\\n        return result;\\n    }\\n\\n    /*\\n     * @dev A cheaper version of toRlpBytes(item) that avoids copying memory.\\n     *      This will destroy the original data.\\n     * @return RLP encoded bytes.\\n     */\\n    function unsafeToRlpBytes(RLPItem memory item) internal pure returns (bytes memory result) {\\n        if (item.len == 0) return result;\\n\\n        uint256 len = item.len;\\n        uint256 memPtr = item.memPtr;\\n\\n        assembly {\\n            result := sub(memPtr, 0x20)\\n            mstore(result, len)\\n        }\\n        return result;\\n    }\\n\\n    /*\\n     * @dev A cheaper version of toBytes(item) that avoids copying memory.\\n     *      This will destroy the original data.\\n     * @return RLP encoded bytes.\\n     */\\n    function unsafeToBytes(RLPItem memory item) internal pure returns (bytes memory result) {\\n        if (item.len == 0) return result;\\n\\n        (uint256 memPtr, uint256 len) = payloadLocation(item);\\n        assembly {\\n            result := sub(memPtr, 0x20)\\n            mstore(result, len)\\n        }\\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) 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 (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) 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(uint256 src, uint256 dest, uint256 len) 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\":\"0x642623846e9c7012604b3a50d29ec428ecd68def76a7d0a937b8458bea5c7b66\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b50610fad806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c58b5b6214610030575b600080fd5b61004361003e366004610bf0565b610057565b604051901515815260200160405180910390f35b600061006582858588610070565b90505b949350505050565b8251600090606090819084908490889061009257600095505050505050610068565b60005b88518110156102fa5781518311156100b65760009650505050505050610068565b8881815181106100c8576100c8610f4b565b60200260200101519550858051906020012084146100ef5760009650505050505050610068565b61014161013c8a838151811061010757610107610f4b565b602002602001015160408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61030b565b94508451601114156102165781518314156101a5578a805190602001206101818660108151811061017457610174610f4b565b6020026020010151610458565b14156101965760019650505050505050610068565b60009650505050505050610068565b60008284815181106101b9576101b9610f4b565b016020015160f81c905060108111156101dc576000975050505050505050610068565b610201868260ff16815181106101f4576101f4610f4b565b6020026020010151610470565b945061020e600185610d3c565b9350506102e8565b84516002141561019657600061024f6102488760008151811061023b5761023b610f4b565b60200260200101516104e1565b8486610595565b835190915061025e8286610d3c565b14156102a8578b805190602001206102828760018151811061017457610174610f4b565b1415610298576001975050505050505050610068565b6000975050505050505050610068565b806102bd576000975050505050505050610068565b6102c78185610d3c565b93506102df866001815181106101f4576101f4610f4b565b94506102e89050565b806102f281610ece565b915050610095565b5060009a9950505050505050505050565b60606103168261069f565b6103565760405162461bcd60e51b815260206004820152600c60248201526b1a5cc81b1a5cdd0819985a5b60a21b60448201526064015b60405180910390fd5b6000610361836106d8565b905060008167ffffffffffffffff81111561037e5761037e610f61565b6040519080825280602002602001820160405280156103c357816020015b604080518082019091526000808252602082015281526020019060019003908161039c5790505b50905060006103d5856020015161075b565b85602001516103e49190610d3c565b90506000805b8481101561044d576103fb836107dd565b915060405180604001604052808381526020018481525084828151811061042457610424610f4b565b60209081029190910101526104398284610d3c565b92508061044581610ece565b9150506103ea565b509195945050505050565b600080600061046684610886565b9020949350505050565b80516000906021146104c45760405162461bcd60e51b815260206004820152601760248201527f6974656d206973206e6f742075696e7420737472696374000000000000000000604482015260640161034d565b600080836020015160016104d89190610d3c565b51949350505050565b80516060906105255760405162461bcd60e51b815260206004820152601060248201526f6974656d206c656e206973207a65726f60801b604482015260640161034d565b60008061053184610886565b9150915060008167ffffffffffffffff81111561055057610550610f61565b6040519080825280601f01601f19166020018201604052801561057a576020820181803683370190505b5090506020810161058c8482856108cd565b50949350505050565b60008060006105a38661094d565b90506000815167ffffffffffffffff8111156105c1576105c1610f61565b6040519080825280601f01601f1916602001820160405280156105eb576020820181803683370190505b509050845b82516105fc9087610d3c565b81101561066f57600087828151811061061757610617610f4b565b01602001516001600160f81b031916905080836106348985610e94565b8151811061064457610644610f4b565b60200101906001600160f81b031916908160001a90535050808061066790610ece565b9150506105f0565b5080805190602001208280519060200120141561068f5781519250610694565b600092505b509095945050505050565b80516000906106b057506000919050565b6020820151805160001a9060c08210156106ce575060009392505050565b5060019392505050565b80516000906106e957506000919050565b6000806106f9846020015161075b565b84602001516107089190610d3c565b90506000846000015185602001516107209190610d3c565b90505b8082101561075257610734826107dd565b61073e9083610d3c565b91508261074a81610ece565b935050610723565b50909392505050565b8051600090811a60808110156107745750600092915050565b60b881108061078f575060c0811080159061078f575060f881105b1561079d5750600192915050565b60c08110156107d1576107b2600160b8610eab565b6107bf9060ff1682610e94565b6107ca906001610d3c565b9392505050565b6107b2600160f8610eab565b80516000908190811a60808110156107f8576001915061087f565b60b881101561081e5761080c608082610e94565b610817906001610d3c565b915061087f565b60c081101561084b5760b78103600185019450806020036101000a8551046001820181019350505061087f565b60f881101561085f5761080c60c082610e94565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b6000806000610898846020015161075b565b905060008185602001516108ac9190610d3c565b905060008286600001516108c09190610e94565b9196919550909350505050565b806108d757505050565b6020811061090f57825182526108ee602084610d3c565b92506108fb602083610d3c565b9150610908602082610e94565b90506108d7565b80156109485760006001610924836020610e94565b61093090610100610dcd565b61093a9190610e94565b845184518216911916178352505b505050565b606080600083511115610af957600080610968600086610aff565b60f81c9050600181148061097f57508060ff166003145b15610a27576001855160026109949190610e75565b61099e9190610e94565b67ffffffffffffffff8111156109b6576109b6610f61565b6040519080825280601f01601f1916602001820160405280156109e0576020820181803683370190505b50925060006109f0600187610aff565b90508084600081518110610a0657610a06610f4b565b60200101906001600160f81b031916908160001a9053506001925050610a8b565b600285516002610a379190610e75565b610a419190610e94565b67ffffffffffffffff811115610a5957610a59610f61565b6040519080825280601f01601f191660200182016040528015610a83576020820181803683370190505b509250600091505b60ff82165b8351811015610af557610aba610aa960ff851683610e94565b610ab4906002610d3c565b87610aff565b848281518110610acc57610acc610f4b565b60200101906001600160f81b031916908160001a90535080610aed81610ece565b915050610a90565b5050505b92915050565b6000610b0c600284610ee9565b15610b4657601082610b1f600286610d54565b81518110610b2f57610b2f610f4b565b0160200151610b41919060f81c610efd565b610b76565b601082610b54600286610d54565b81518110610b6457610b64610f4b565b0160200151610b76919060f81c610d68565b60f81b9392505050565b600082601f830112610b9157600080fd5b813567ffffffffffffffff811115610bab57610bab610f61565b610bbe601f8201601f1916602001610d0b565b818152846020838601011115610bd357600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215610c0657600080fd5b8435935060208086013567ffffffffffffffff80821115610c2657600080fd5b610c3289838a01610b80565b95506040880135915080821115610c4857600080fd5b818801915088601f830112610c5c57600080fd5b813581811115610c6e57610c6e610f61565b8060051b610c7d858201610d0b565b8281528581019085870183870188018e1015610c9857600080fd5b600093505b84841015610cd757803586811115610cb457600080fd5b610cc28f8a838b0101610b80565b84525060019390930192918701918701610c9d565b5097505050506060880135925080831115610cf157600080fd5b5050610cff87828801610b80565b91505092959194509250565b604051601f8201601f1916810167ffffffffffffffff81118282101715610d3457610d34610f61565b604052919050565b60008219821115610d4f57610d4f610f1f565b500190565b600082610d6357610d63610f35565b500490565b600060ff831680610d7b57610d7b610f35565b8060ff84160491505092915050565b600181815b80851115610dc5578160001904821115610dab57610dab610f1f565b80851615610db857918102915b93841c9390800290610d8f565b509250929050565b60006107ca8383600082610de357506001610af9565b81610df057506000610af9565b8160018114610e065760028114610e1057610e2c565b6001915050610af9565b60ff841115610e2157610e21610f1f565b50506001821b610af9565b5060208310610133831016604e8410600b8410161715610e4f575081810a610af9565b610e598383610d8a565b8060001904821115610e6d57610e6d610f1f565b029392505050565b6000816000190483118215151615610e8f57610e8f610f1f565b500290565b600082821015610ea657610ea6610f1f565b500390565b600060ff821660ff841680821015610ec557610ec5610f1f565b90039392505050565b6000600019821415610ee257610ee2610f1f565b5060010190565b600082610ef857610ef8610f35565b500690565b600060ff831680610f1057610f10610f35565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220ee0db34160a9b89daea7f70292a4ae0e3f878c702d6108ae6c78a2435a3c766f64736f6c63430008070033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c58b5b6214610030575b600080fd5b61004361003e366004610bf0565b610057565b604051901515815260200160405180910390f35b600061006582858588610070565b90505b949350505050565b8251600090606090819084908490889061009257600095505050505050610068565b60005b88518110156102fa5781518311156100b65760009650505050505050610068565b8881815181106100c8576100c8610f4b565b60200260200101519550858051906020012084146100ef5760009650505050505050610068565b61014161013c8a838151811061010757610107610f4b565b602002602001015160408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61030b565b94508451601114156102165781518314156101a5578a805190602001206101818660108151811061017457610174610f4b565b6020026020010151610458565b14156101965760019650505050505050610068565b60009650505050505050610068565b60008284815181106101b9576101b9610f4b565b016020015160f81c905060108111156101dc576000975050505050505050610068565b610201868260ff16815181106101f4576101f4610f4b565b6020026020010151610470565b945061020e600185610d3c565b9350506102e8565b84516002141561019657600061024f6102488760008151811061023b5761023b610f4b565b60200260200101516104e1565b8486610595565b835190915061025e8286610d3c565b14156102a8578b805190602001206102828760018151811061017457610174610f4b565b1415610298576001975050505050505050610068565b6000975050505050505050610068565b806102bd576000975050505050505050610068565b6102c78185610d3c565b93506102df866001815181106101f4576101f4610f4b565b94506102e89050565b806102f281610ece565b915050610095565b5060009a9950505050505050505050565b60606103168261069f565b6103565760405162461bcd60e51b815260206004820152600c60248201526b1a5cc81b1a5cdd0819985a5b60a21b60448201526064015b60405180910390fd5b6000610361836106d8565b905060008167ffffffffffffffff81111561037e5761037e610f61565b6040519080825280602002602001820160405280156103c357816020015b604080518082019091526000808252602082015281526020019060019003908161039c5790505b50905060006103d5856020015161075b565b85602001516103e49190610d3c565b90506000805b8481101561044d576103fb836107dd565b915060405180604001604052808381526020018481525084828151811061042457610424610f4b565b60209081029190910101526104398284610d3c565b92508061044581610ece565b9150506103ea565b509195945050505050565b600080600061046684610886565b9020949350505050565b80516000906021146104c45760405162461bcd60e51b815260206004820152601760248201527f6974656d206973206e6f742075696e7420737472696374000000000000000000604482015260640161034d565b600080836020015160016104d89190610d3c565b51949350505050565b80516060906105255760405162461bcd60e51b815260206004820152601060248201526f6974656d206c656e206973207a65726f60801b604482015260640161034d565b60008061053184610886565b9150915060008167ffffffffffffffff81111561055057610550610f61565b6040519080825280601f01601f19166020018201604052801561057a576020820181803683370190505b5090506020810161058c8482856108cd565b50949350505050565b60008060006105a38661094d565b90506000815167ffffffffffffffff8111156105c1576105c1610f61565b6040519080825280601f01601f1916602001820160405280156105eb576020820181803683370190505b509050845b82516105fc9087610d3c565b81101561066f57600087828151811061061757610617610f4b565b01602001516001600160f81b031916905080836106348985610e94565b8151811061064457610644610f4b565b60200101906001600160f81b031916908160001a90535050808061066790610ece565b9150506105f0565b5080805190602001208280519060200120141561068f5781519250610694565b600092505b509095945050505050565b80516000906106b057506000919050565b6020820151805160001a9060c08210156106ce575060009392505050565b5060019392505050565b80516000906106e957506000919050565b6000806106f9846020015161075b565b84602001516107089190610d3c565b90506000846000015185602001516107209190610d3c565b90505b8082101561075257610734826107dd565b61073e9083610d3c565b91508261074a81610ece565b935050610723565b50909392505050565b8051600090811a60808110156107745750600092915050565b60b881108061078f575060c0811080159061078f575060f881105b1561079d5750600192915050565b60c08110156107d1576107b2600160b8610eab565b6107bf9060ff1682610e94565b6107ca906001610d3c565b9392505050565b6107b2600160f8610eab565b80516000908190811a60808110156107f8576001915061087f565b60b881101561081e5761080c608082610e94565b610817906001610d3c565b915061087f565b60c081101561084b5760b78103600185019450806020036101000a8551046001820181019350505061087f565b60f881101561085f5761080c60c082610e94565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b6000806000610898846020015161075b565b905060008185602001516108ac9190610d3c565b905060008286600001516108c09190610e94565b9196919550909350505050565b806108d757505050565b6020811061090f57825182526108ee602084610d3c565b92506108fb602083610d3c565b9150610908602082610e94565b90506108d7565b80156109485760006001610924836020610e94565b61093090610100610dcd565b61093a9190610e94565b845184518216911916178352505b505050565b606080600083511115610af957600080610968600086610aff565b60f81c9050600181148061097f57508060ff166003145b15610a27576001855160026109949190610e75565b61099e9190610e94565b67ffffffffffffffff8111156109b6576109b6610f61565b6040519080825280601f01601f1916602001820160405280156109e0576020820181803683370190505b50925060006109f0600187610aff565b90508084600081518110610a0657610a06610f4b565b60200101906001600160f81b031916908160001a9053506001925050610a8b565b600285516002610a379190610e75565b610a419190610e94565b67ffffffffffffffff811115610a5957610a59610f61565b6040519080825280601f01601f191660200182016040528015610a83576020820181803683370190505b509250600091505b60ff82165b8351811015610af557610aba610aa960ff851683610e94565b610ab4906002610d3c565b87610aff565b848281518110610acc57610acc610f4b565b60200101906001600160f81b031916908160001a90535080610aed81610ece565b915050610a90565b5050505b92915050565b6000610b0c600284610ee9565b15610b4657601082610b1f600286610d54565b81518110610b2f57610b2f610f4b565b0160200151610b41919060f81c610efd565b610b76565b601082610b54600286610d54565b81518110610b6457610b64610f4b565b0160200151610b76919060f81c610d68565b60f81b9392505050565b600082601f830112610b9157600080fd5b813567ffffffffffffffff811115610bab57610bab610f61565b610bbe601f8201601f1916602001610d0b565b818152846020838601011115610bd357600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215610c0657600080fd5b8435935060208086013567ffffffffffffffff80821115610c2657600080fd5b610c3289838a01610b80565b95506040880135915080821115610c4857600080fd5b818801915088601f830112610c5c57600080fd5b813581811115610c6e57610c6e610f61565b8060051b610c7d858201610d0b565b8281528581019085870183870188018e1015610c9857600080fd5b600093505b84841015610cd757803586811115610cb457600080fd5b610cc28f8a838b0101610b80565b84525060019390930192918701918701610c9d565b5097505050506060880135925080831115610cf157600080fd5b5050610cff87828801610b80565b91505092959194509250565b604051601f8201601f1916810167ffffffffffffffff81118282101715610d3457610d34610f61565b604052919050565b60008219821115610d4f57610d4f610f1f565b500190565b600082610d6357610d63610f35565b500490565b600060ff831680610d7b57610d7b610f35565b8060ff84160491505092915050565b600181815b80851115610dc5578160001904821115610dab57610dab610f1f565b80851615610db857918102915b93841c9390800290610d8f565b509250929050565b60006107ca8383600082610de357506001610af9565b81610df057506000610af9565b8160018114610e065760028114610e1057610e2c565b6001915050610af9565b60ff841115610e2157610e21610f1f565b50506001821b610af9565b5060208310610133831016604e8410600b8410161715610e4f575081810a610af9565b610e598383610d8a565b8060001904821115610e6d57610e6d610f1f565b029392505050565b6000816000190483118215151615610e8f57610e8f610f1f565b500290565b600082821015610ea657610ea6610f1f565b500390565b600060ff821660ff841680821015610ec557610ec5610f1f565b90039392505050565b6000600019821415610ee257610ee2610f1f565b5060010190565b600082610ef857610ef8610f35565b500690565b600060ff831680610f1057610f10610f35565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220ee0db34160a9b89daea7f70292a4ae0e3f878c702d6108ae6c78a2435a3c766f64736f6c63430008070033",
  "devdoc": {
    "kind": "dev",
    "methods": {},
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [],
    "types": null
  }
}