{
  "language": "Solidity",
  "sources": {
    "contracts/interfaces/ILayerZeroValidationLibrary.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\npragma abicoder v2;\n\nimport \"../utility/LayerZeroPacket.sol\";\n\ninterface ILayerZeroValidationLibrary {\n    function validateProof(bytes32 blockData, bytes calldata _data, uint _remoteAddressSize) external returns (LayerZeroPacket.Packet memory packet);\n}\n"
    },
    "contracts/utility/LayerZeroPacket.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"./Buffer.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nlibrary LayerZeroPacket {\n    using Buffer for Buffer.buffer;\n    using SafeMath for uint;\n\n    struct Packet {\n        uint16 srcChainId;\n        uint16 dstChainId;\n        uint64 nonce;\n        address dstAddress;\n        bytes srcAddress;\n        bytes32 ulnAddress;\n        bytes payload;\n    }\n\n    function getPacket(\n        bytes memory data,\n        uint16 srcChain,\n        uint sizeOfSrcAddress,\n        bytes32 ulnAddress\n    ) internal pure returns (LayerZeroPacket.Packet memory) {\n        uint16 dstChainId;\n        address dstAddress;\n        uint size;\n        uint64 nonce;\n\n        // The log consists of the destination chain id and then a bytes payload\n        //      0--------------------------------------------31\n        // 0   |  total bytes size\n        // 32  |  destination chain id\n        // 64  |  bytes offset\n        // 96  |  bytes array size\n        // 128 |  payload\n        assembly {\n            dstChainId := mload(add(data, 32))\n            size := mload(add(data, 96)) /// size of the byte array\n            nonce := mload(add(data, 104)) // offset to convert to uint64  128  is index -24\n            dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n        }\n\n        Buffer.buffer memory srcAddressBuffer;\n        srcAddressBuffer.init(sizeOfSrcAddress);\n        srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n        uint payloadSize = size.sub(28).sub(sizeOfSrcAddress);\n        Buffer.buffer memory payloadBuffer;\n        payloadBuffer.init(payloadSize);\n        payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n        return LayerZeroPacket.Packet(srcChain, dstChainId, nonce, dstAddress, srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);\n    }\n}\n"
    },
    "contracts/utility/Buffer.sol": {
      "content": "// SPDX-License-Identifier: BSD-2-Clause\n// https://github.com/ensdomains/buffer\n\npragma solidity ^0.7.0;\n\n/**\n * @dev A library for working with mutable byte buffers in Solidity.\n *\n * Byte buffers are mutable and expandable, and provide a variety of primitives\n * for writing to them. At any time you can fetch a bytes object containing the\n * current contents of the buffer. The bytes object should not be stored between\n * operations, as it may change due to resizing of the buffer.\n */\nlibrary Buffer {\n    /**\n     * @dev Represents a mutable buffer. Buffers have a current value (buf) and\n     *      a capacity. The capacity may be longer than the current value, in\n     *      which case it can be extended without the need to allocate more memory.\n     */\n    struct buffer {\n        bytes buf;\n        uint capacity;\n    }\n\n    /**\n     * @dev Initializes a buffer with an initial capacity.a co\n     * @param buf The buffer to initialize.\n     * @param capacity The number of bytes of space to allocate the buffer.\n     * @return The buffer, for chaining.\n     */\n    function init(buffer memory buf, uint capacity) internal pure returns (buffer memory) {\n        if (capacity % 32 != 0) {\n            capacity += 32 - (capacity % 32);\n        }\n        // Allocate space for the buffer data\n        buf.capacity = capacity;\n        assembly {\n            let ptr := mload(0x40)\n            mstore(buf, ptr)\n            mstore(ptr, 0)\n            mstore(0x40, add(32, add(ptr, capacity)))\n        }\n        return buf;\n    }\n\n\n    /**\n     * @dev Writes a byte string to a buffer. Resizes if doing so would exceed\n     *      the capacity of the buffer.\n     * @param buf The buffer to append to.\n     * @param off The start offset to write to.\n     * @param rawData The data to append.\n     * @param len The number of bytes to copy.\n     * @return The original buffer, for chaining.\n     */\n    function writeRawBytes(\n        buffer memory buf,\n        uint off,\n        bytes memory rawData,\n        uint offData,\n        uint len\n    ) internal pure returns (buffer memory) {\n        if (off + len > buf.capacity) {\n            resize(buf, max(buf.capacity, len + off) * 2);\n        }\n\n        uint dest;\n        uint src;\n        assembly {\n            // Memory address of the buffer data\n            let bufptr := mload(buf)\n            // Length of existing buffer data\n            let buflen := mload(bufptr)\n            // Start address = buffer address + offset + sizeof(buffer length)\n            dest := add(add(bufptr, 32), off)\n            // Update buffer length if we're extending it\n            if gt(add(len, off), buflen) {\n                mstore(bufptr, add(len, off))\n            }\n            src := add(rawData, offData)\n        }\n\n        // Copy word-length chunks while possible\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        // Copy remaining bytes\n        uint mask = 256**(32 - len) - 1;\n        assembly {\n            let srcpart := and(mload(src), not(mask))\n            let destpart := and(mload(dest), mask)\n            mstore(dest, or(destpart, srcpart))\n        }\n\n        return buf;\n    }\n\n    /**\n     * @dev Writes a byte string to a buffer. Resizes if doing so would exceed\n     *      the capacity of the buffer.\n     * @param buf The buffer to append to.\n     * @param off The start offset to write to.\n     * @param data The data to append.\n     * @param len The number of bytes to copy.\n     * @return The original buffer, for chaining.\n     */\n    function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns (buffer memory) {\n        require(len <= data.length);\n\n        if (off + len > buf.capacity) {\n            resize(buf, max(buf.capacity, len + off) * 2);\n        }\n\n        uint dest;\n        uint src;\n        assembly {\n        // Memory address of the buffer data\n            let bufptr := mload(buf)\n        // Length of existing buffer data\n            let buflen := mload(bufptr)\n        // Start address = buffer address + offset + sizeof(buffer length)\n            dest := add(add(bufptr, 32), off)\n        // Update buffer length if we're extending it\n            if gt(add(len, off), buflen) {\n                mstore(bufptr, add(len, off))\n            }\n            src := add(data, 32)\n        }\n\n        // Copy word-length chunks while possible\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        // Copy remaining bytes\n        uint mask = 256**(32 - len) - 1;\n        assembly {\n            let srcpart := and(mload(src), not(mask))\n            let destpart := and(mload(dest), mask)\n            mstore(dest, or(destpart, srcpart))\n        }\n\n        return buf;\n    }\n\n    function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\n        return write(buf, buf.buf.length, data, data.length);\n    }\n\n    function resize(buffer memory buf, uint capacity) private pure {\n        bytes memory oldbuf = buf.buf;\n        init(buf, capacity);\n        append(buf, oldbuf);\n    }\n\n    function max(uint a, uint b) private pure returns (uint) {\n        if (a > b) {\n            return a;\n        }\n        return b;\n    }\n}\n"
    },
    "@openzeppelin/contracts/math/SafeMath.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        uint256 c = a + b;\n        if (c < a) return (false, 0);\n        return (true, c);\n    }\n\n    /**\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b > a) return (false, 0);\n        return (true, a - b);\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) return (true, 0);\n        uint256 c = a * b;\n        if (c / a != b) return (false, 0);\n        return (true, c);\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b == 0) return (false, 0);\n        return (true, a / b);\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b == 0) return (false, 0);\n        return (true, a % b);\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c >= a, \"SafeMath: addition overflow\");\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b <= a, \"SafeMath: subtraction overflow\");\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (a == 0) return 0;\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b > 0, \"SafeMath: division by zero\");\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b > 0, \"SafeMath: modulo by zero\");\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b <= a, errorMessage);\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b > 0, errorMessage);\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b > 0, errorMessage);\n        return a % b;\n    }\n}\n"
    },
    "contracts/MPTValidatorV2.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/Buffer.sol\";\nimport \"./interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ncontract MPTValidatorV2 is ILayerZeroValidationLibrary {\n    using RLPDecode for RLPDecode.RLPItem;\n    using RLPDecode for RLPDecode.Iterator;\n    using Buffer for Buffer.buffer;\n    using SafeMath for uint;\n\n    bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n    struct ULNLog{\n        bytes32 contractAddress;\n        bytes32 topicZeroSig;\n        bytes data;\n    }\n\n    function validateProof(bytes32 _receiptsRoot, bytes calldata _transactionProof, uint _remoteAddressSize) external pure override returns (LayerZeroPacket.Packet memory packet) {\n        (uint16 remoteChainId, bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(_transactionProof, (uint16, bytes[], uint[], uint));\n\n        ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n        require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n        return _getPacket(log.data, remoteChainId, _remoteAddressSize, log.contractAddress);\n    }\n\n    function _getVerifiedLog(bytes32 hashRoot, uint[] memory paths, uint logIndex, bytes[] memory proof) internal pure returns(ULNLog memory) {\n        require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n\n        RLPDecode.RLPItem memory item;\n        bytes memory proofBytes;\n\n        for (uint i = 0; i < proof.length; i++) {\n            proofBytes = proof[i];\n            require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n            item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n            if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n        }\n\n        // burning status + gasUsed + logBloom\n        RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n        RLPDecode.Iterator memory it =  logItem.safeGetItemByIndex(logIndex).iterator();\n        ULNLog memory log;\n        log.contractAddress = bytes32(it.next().toUint());\n        log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());\n        log.data = it.next().toBytes();\n\n        return log;\n    }\n\n    // profiling and test\n    function getVerifyLog(bytes32 hashRoot, uint[] memory receiptSlotIndex, uint logIndex, bytes[] memory proof) external pure returns(ULNLog memory){\n        return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n    }\n\n    function getPacket(bytes memory data, uint16 srcChain, uint sizeOfSrcAddress, bytes32 ulnAddress) external pure returns(LayerZeroPacket.Packet memory) {\n        return _getPacket(data, srcChain, sizeOfSrcAddress, ulnAddress);\n    }\n\n    function _getPacket(\n        bytes memory data,\n        uint16 srcChain,\n        uint sizeOfSrcAddress,\n        bytes32 ulnAddress\n    ) internal pure returns (LayerZeroPacket.Packet memory) {\n        uint16 dstChainId;\n        address dstAddress;\n        uint size;\n        uint64 nonce;\n\n        // The log consists of the destination chain id and then a bytes payload\n        //      0--------------------------------------------31\n        // 0   |  destination chain id\n        // 32  |  defines bytes array\n        // 64  |\n        // 96  |  bytes array size\n        // 128 |  payload\n        assembly {\n            dstChainId := mload(add(data, 32))\n            size := mload(add(data, 96)) /// size of the byte array\n            nonce := mload(add(data, 104)) // offset to convert to uint64  128  is index -24\n            dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n        }\n\n        Buffer.buffer memory srcAddressBuffer;\n        srcAddressBuffer.init(sizeOfSrcAddress);\n        srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n        uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);\n        Buffer.buffer memory payloadBuffer;\n        payloadBuffer.init(payloadSize);\n        payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n        return LayerZeroPacket.Packet(srcChain, dstChainId, nonce, dstAddress, srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);\n    }\n}\n"
    },
    "contracts/utility/UltraLightNodeEVMDecoder.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.7.0;\npragma abicoder v2;\n\nimport \"./RLPDecode.sol\";\n\nlibrary UltraLightNodeEVMDecoder {\n    using RLPDecode for RLPDecode.RLPItem;\n    using RLPDecode for RLPDecode.Iterator;\n\n    struct Log {\n        address contractAddress;\n        bytes32 topicZero;\n        bytes data;\n    }\n\n    function getReceiptLog(bytes memory data, uint logIndex) internal pure returns (Log memory) {\n        RLPDecode.Iterator memory it = RLPDecode.toRlpItem(data).iterator();\n        uint idx;\n        while (it.hasNext()) {\n            if (idx == 3) {\n                return toReceiptLog(it.next().getItemByIndex(logIndex).toRlpBytes());\n            } else it.next();\n            idx++;\n        }\n        revert(\"no log index in receipt\");\n    }\n\n    function toReceiptLog(bytes memory data) internal pure returns (Log memory) {\n        RLPDecode.Iterator memory it = RLPDecode.toRlpItem(data).iterator();\n        Log memory log;\n\n        uint idx;\n        while (it.hasNext()) {\n            if (idx == 0) {\n                log.contractAddress = it.next().toAddress();\n            } else if (idx == 1) {\n                RLPDecode.RLPItem memory item = it.next().getItemByIndex(0);\n                log.topicZero = bytes32(item.toUint());\n            } else if (idx == 2) log.data = it.next().toBytes();\n            else it.next();\n            idx++;\n        }\n        return log;\n    }\n}\n"
    },
    "contracts/utility/RLPDecode.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0\n// https://github.com/hamdiallam/solidity-rlp\n\npragma solidity ^0.7.0;\n\nlibrary RLPDecode {\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        uint len;\n        uint memPtr;\n    }\n\n    struct Iterator {\n        RLPItem item; // Item that's being iterated over.\n        uint 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), \"RLPDecoder iterator has no next\");\n\n        uint ptr = self.nextPtr;\n        uint 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\n    function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {\n        uint memPtr;\n        assembly {\n            memPtr := add(item, 0x20)\n        }\n        // offset the pointer if the first byte\n\n        uint8 byte0;\n        assembly {\n            byte0 := byte(0, mload(memPtr))\n        }\n        uint len = item.length;\n        if (len > 0 && byte0 < LIST_SHORT_START) {\n            assembly {\n                memPtr := add(memPtr, 0x01)\n            }\n            len -= 1;\n        }\n        return RLPItem(len, 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), \"RLPDecoder iterator is not list\");\n\n        uint ptr = self.memPtr + _payloadOffset(self.memPtr);\n        return Iterator(self, ptr);\n    }\n\n    /*\n     * @param item RLP encoded bytes\n     */\n    function rlpLen(RLPItem memory item) internal pure returns (uint) {\n        return item.len;\n    }\n\n    /*\n     * @param item RLP encoded bytes\n     */\n    function payloadLen(RLPItem memory item) internal pure returns (uint) {\n        uint offset = _payloadOffset(item.memPtr);\n        require(item.len >= offset, \"RLPDecoder: invalid uint RLP item offset size\");\n        return item.len - offset;\n    }\n\n    /*\n     * @param item RLP encoded list in bytes\n     */\n    function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {\n        require(isList(item), \"RLPDecoder iterator is not a list\");\n\n        uint items = numItems(item);\n        RLPItem[] memory result = new RLPItem[](items);\n\n        uint memPtr = item.memPtr + _payloadOffset(item.memPtr);\n        uint dataLen;\n        for (uint 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), \"RLPDecoder iterator is not a list\");\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    /*\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), \"RLPDecoder iterator is not a list\");\n        require(idx < numItems(item), \"RLP item out of bounds\");\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    /*\n     * @param offset the receipt bytes item\n     */\n    function typeOffset(RLPItem memory item) internal pure returns (RLPItem memory) {\n        uint offset = _payloadOffset(item.memPtr);\n        uint8 byte0;\n        uint memPtr = item.memPtr;\n        uint len = item.len;\n        assembly {\n            memPtr := add(memPtr, offset)\n            byte0 := byte(0, mload(memPtr))\n        }\n        if (len >0 && byte0 < LIST_SHORT_START) {\n            assembly {\n                memPtr := add(memPtr, 0x01)\n            }\n            len -= 1;\n        }\n        return RLPItem(len, 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        uint 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    /** 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        uint 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, \"RLPDecoder toBoolean invalid length\");\n        uint result;\n        uint 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, \"RLPDecoder toAddress invalid length\");\n\n        return address(toUint(item));\n    }\n\n    function toUint(RLPItem memory item) internal pure returns (uint) {\n        require(item.len > 0 && item.len <= 33, \"RLPDecoder toUint invalid length\");\n\n        uint offset = _payloadOffset(item.memPtr);\n        require(item.len >= offset, \"RLPDecoder: invalid RLP item offset size\");\n        uint len = item.len - offset;\n\n        uint result;\n        uint memPtr = item.memPtr + offset;\n        assembly {\n            result := mload(memPtr)\n\n            // shift to the correct location if necessary\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 (uint) {\n        // one byte prefix\n        require(item.len == 33, \"RLPDecoder toUintStrict invalid length\");\n\n        uint result;\n        uint 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, \"RLPDecoder toBytes invalid length\");\n\n        uint offset = _payloadOffset(item.memPtr);\n        require(item.len >= offset, \"RLPDecoder: invalid RLP item offset size\");\n        uint len = item.len - offset; // data length\n        bytes memory result = new bytes(len);\n\n        uint destPtr;\n        assembly {\n            destPtr := add(0x20, result)\n        }\n\n        copy(item.memPtr + offset, 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 (uint) {\n        if (item.len == 0) return 0;\n\n        uint count = 0;\n        uint currPtr = item.memPtr + _payloadOffset(item.memPtr);\n        uint endPtr = item.memPtr + item.len;\n        while (currPtr < endPtr) {\n            currPtr = currPtr + _itemLength(currPtr); // skip over an item\n            count++;\n        }\n\n        return count;\n    }\n\n    // @return entire rlp item byte length\n    function _itemLength(uint memPtr) private pure returns (uint) {\n        uint itemLen;\n        uint 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(uint memPtr) private pure returns (uint) {\n        uint 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(\n        uint src,\n        uint dest,\n        uint 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        // left over bytes. Mask is used to remove unwanted bytes from the word\n        uint 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"
    },
    "contracts/MPTValidatorV5.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./interfaces/IValidationLibraryHelper.sol\";\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/PacketDecoder.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ninterface IUltraLightNode {\n    struct BlockData {\n        uint confirmations;\n        bytes32 data;\n    }\n\n    struct ApplicationConfiguration {\n        uint16 inboundProofLibraryVersion;\n        uint64 inboundBlockConfirmations;\n        address relayer;\n        uint16 outboundProofType;\n        uint64 outboundBlockConfirmations;\n        address oracle;\n    }\n\n    function getAppConfig(uint16 _chainId, address userApplicationAddress) external view returns (ApplicationConfiguration memory);\n    function getBlockHeaderData(address _oracle, uint16 _remoteChainId, bytes32 _lookupHash) external view returns (BlockData memory blockData);\n}\n\ninterface IStargate {\n    // Stargate objects for abi encoding / decoding\n    struct SwapObj {\n        uint256 amount;\n        uint256 eqFee;\n        uint256 eqReward;\n        uint256 lpFee;\n        uint256 protocolFee;\n        uint256 lkbRemove;\n    }\n\n    struct CreditObj {\n        uint256 credits;\n        uint256 idealBalance;\n    }\n}\n\ncontract MPTValidatorV5 is ILayerZeroValidationLibrary, IValidationLibraryHelper {\n    using RLPDecode for RLPDecode.RLPItem;\n    using RLPDecode for RLPDecode.Iterator;\n    using PacketDecoder for bytes;\n\n    uint8 public utilsVersion = 3;\n    bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n    address immutable public stargateBridgeAddress;\n    address immutable public stgTokenAddress;\n    address immutable public relayerAddress;\n    uint16 immutable public localChainId;\n    IUltraLightNode immutable public uln;\n\n    constructor (address _stargateBridgeAddress, address _stgTokenAddress, uint16 _localChainId, address _ulnAddress, address _relayerAddress) {\n        stargateBridgeAddress = _stargateBridgeAddress;\n        stgTokenAddress = _stgTokenAddress;\n        localChainId = _localChainId;\n        uln = IUltraLightNode(_ulnAddress);\n        relayerAddress = _relayerAddress;\n    }\n\n    function validateProof(bytes32 _receiptsRoot, bytes calldata _transactionProof, uint _remoteAddressSize) external view override returns (LayerZeroPacket.Packet memory) {\n        require(_remoteAddressSize > 0, \"ProofLib: invalid address size\");\n\n        (uint16 remoteChainId, bytes32 blockHash, bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(_transactionProof, (uint16, bytes32, bytes[], uint[], uint));\n\n        ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n        require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n        LayerZeroPacket.Packet memory packet = log.data.getPacket(remoteChainId, _remoteAddressSize, log.contractAddress);\n\n        _assertMessagePath(packet, blockHash, _receiptsRoot);\n\n        if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n\n        if (packet.dstAddress == stgTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n        return packet;\n    }\n\n    function _assertMessagePath(LayerZeroPacket.Packet memory packet, bytes32 blockHash, bytes32 receiptsRoot) internal view {\n        require(packet.dstChainId == localChainId, \"ProofLib: invalid destination chain ID\");\n\n        IUltraLightNode.ApplicationConfiguration memory appConfig = uln.getAppConfig(packet.srcChainId, packet.dstAddress);\n        IUltraLightNode.BlockData memory blockData = uln.getBlockHeaderData(appConfig.oracle, packet.srcChainId, blockHash);\n        require(appConfig.relayer == relayerAddress, \"ProofLib: invalid relayer\");\n\n        require(blockData.data == receiptsRoot, \"ProofLib: invalid receipt root\");\n\n        require(blockData.confirmations >= appConfig.inboundBlockConfirmations, \"ProofLib: not enough block confirmations\");\n    }\n\n    function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n        (bytes memory toAddressBytes, uint256 qty) = abi.decode(_payload, (bytes, uint256));\n\n        address toAddress = address(0);\n        if (toAddressBytes.length > 0) {\n            assembly { toAddress := mload(add(toAddressBytes, 20))}\n        }\n\n        if (toAddress == address(0)) {\n            address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n            bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n            return abi.encode(newToAddressBytes, qty);\n        }\n\n        // default to return the original payload\n        return _payload;\n    }\n\n    function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n        // functionType is uint8 even though the encoding will take up the side of uint256\n        uint8 functionType;\n        assembly { functionType := mload(add(_payload, 32)) }\n\n        // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n        // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n        // thus we do not care about the other type functions even if the toAddress is overly long.\n        if (functionType == 1) {\n            // decode the _payload with its types\n            (\n                ,\n                uint256 srcPoolId,\n                uint256 dstPoolId,\n                uint256 dstGasForCall,\n                IStargate.CreditObj memory c,\n                IStargate.SwapObj memory s,\n                bytes memory toAddressBytes,\n                bytes memory contractCallPayload\n            ) = abi.decode(_payload, (uint8, uint256, uint256, uint256, IStargate.CreditObj, IStargate.SwapObj, bytes, bytes));\n\n            // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n            if (contractCallPayload.length > 0) {\n                // otherwise, need to check if the payload can be delivered to the toAddress\n                address toAddress = address(0);\n                if (toAddressBytes.length > 0) {\n                    assembly { toAddress := mload(add(toAddressBytes, 20)) }\n                }\n\n                // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n                // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n                uint size;\n                assembly { size := extcodesize(toAddress) }\n\n                if (size == 0) {\n                    // size == 0 indicates its not a contract, payload wont be delivered\n                    // secure the _payload to make sure funds can be delivered to the toAddress\n                    bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n                    bytes memory securePayload = abi.encode(functionType, srcPoolId, dstPoolId, dstGasForCall, c, s, newToAddressBytes, bytes(\"\"));\n                    return securePayload;\n                }\n            }\n        }\n\n        // default to return the original payload\n        return _payload;\n    }\n\n    function secureStgTokenPayload(bytes memory _payload) external pure returns(bytes memory) {\n        return _secureStgTokenPayload(_payload);\n    }\n\n    function secureStgPayload(bytes memory _payload) external view returns(bytes memory) {\n        return _secureStgPayload(_payload);\n    }\n\n    function _getVerifiedLog(bytes32 hashRoot, uint[] memory paths, uint logIndex, bytes[] memory proof) internal pure returns(ULNLog memory) {\n        require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n        require(proof.length >0, \"ProofLib: proof size must > 0\");\n        RLPDecode.RLPItem memory item;\n        bytes memory proofBytes;\n\n        for (uint i = 0; i < proof.length; i++) {\n            proofBytes = proof[i];\n            require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n            item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n            if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n        }\n\n        // burning status + gasUsed + logBloom\n        RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n        RLPDecode.Iterator memory it =  logItem.safeGetItemByIndex(logIndex).iterator();\n        ULNLog memory log;\n        log.contractAddress = bytes32(it.next().toUint());\n        log.topicZeroSig = bytes32(it.next().safeGetItemByIndex(0).toUint());\n        log.data = it.next().toBytes();\n\n        return log;\n    }\n\n    function getUtilsVersion() external override view returns(uint8) {\n        return utilsVersion;\n    }\n\n    function getVerifyLog(bytes32 hashRoot, uint[] memory receiptSlotIndex, uint logIndex, bytes[] memory proof) external override pure returns(ULNLog memory){\n        return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n    }\n\n    function getPacket(bytes memory data, uint16 srcChain, uint sizeOfSrcAddress, bytes32 ulnAddress) external override pure returns(LayerZeroPacket.Packet memory){\n        return data.getPacket(srcChain, sizeOfSrcAddress, ulnAddress);\n    }\n\n    // profiling and test\n    function assertMessagePath(LayerZeroPacket.Packet memory packet, bytes32 blockHash, bytes32 receiptsRoot) external view {\n        _assertMessagePath(packet, blockHash, receiptsRoot);\n    }\n}\n"
    },
    "contracts/interfaces/IValidationLibraryHelper.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\npragma abicoder v2;\n\nimport \"../utility/LayerZeroPacket.sol\";\nimport \"./ILayerZeroValidationLibrary.sol\";\n\ninterface IValidationLibraryHelper {\n    struct ULNLog{\n        bytes32 contractAddress;\n        bytes32 topicZeroSig;\n        bytes data;\n    }\n\n    function getVerifyLog(bytes32 hashRoot, uint[] memory receiptSlotIndex, uint logIndex, bytes[] memory proof) external pure returns(ULNLog memory);\n    function getPacket(bytes memory data, uint16 srcChain, uint sizeOfSrcAddress, bytes32 ulnAddress) external pure returns(LayerZeroPacket.Packet memory);\n    function getUtilsVersion() external view returns(uint8);\n}\n"
    },
    "contracts/utility/PacketDecoder.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./LayerZeroPacket.sol\";\n\nlibrary PacketDecoder {\n    using Buffer for Buffer.buffer;\n    using SafeMath for uint;\n\n    function getPacket(\n        bytes memory data,\n        uint16 srcChain,\n        uint sizeOfSrcAddress,\n        bytes32 ulnAddress\n    ) internal pure returns (LayerZeroPacket.Packet memory) {\n        uint16 dstChainId;\n        address dstAddress;\n        uint size;\n        uint64 nonce;\n\n        // The log consists of the destination chain id and then a bytes payload\n        //      0--------------------------------------------31\n        // 0   |  total bytes size\n        // 32  |  destination chain id\n        // 64  |  bytes offset\n        // 96  |  bytes array size\n        // 128 |  payload\n        assembly {\n            dstChainId := mload(add(data, 32))\n            size := mload(add(data, 96)) /// size of the byte array\n            nonce := mload(add(data, 104)) // offset to convert to uint64  128  is index -24\n            dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n        }\n\n        Buffer.buffer memory srcAddressBuffer;\n        srcAddressBuffer.init(sizeOfSrcAddress);\n        srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n        uint payloadSize = size.sub(28).sub(sizeOfSrcAddress);\n        Buffer.buffer memory payloadBuffer;\n        payloadBuffer.init(payloadSize);\n        payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n        return LayerZeroPacket.Packet(srcChain, dstChainId, nonce, dstAddress, srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);\n    }\n}\n"
    },
    "contracts/test/TestPacketDecoder.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.7.6;\npragma abicoder v2;\nimport \"../utility/LayerZeroPacket.sol\";\nimport \"../utility/PacketDecoder.sol\";\n\ncontract TestPacketDecoder {\n    function testUaPayload(uint64 nonce, uint16 srcChainId, address srcAddress, uint16 dstChainId, bytes memory dstAddress, bytes memory payload) external pure returns(LayerZeroPacket.Packet memory) {\n//        bytes memory encodedPayload = abi.encodePacked(nonce, ua, _destination, _payload);\n//        emit Packet(chainId, encodedPayload);\n        bytes memory encodedPayload = abi.encodePacked(nonce, srcAddress, dstAddress, payload);\n        bytes memory fullPayload = abi.encode(dstChainId, encodedPayload);\n        return testFullPayload(fullPayload, srcChainId, 20, bytes32(0));\n    }\n\n    function testFullPayload(bytes memory payload, uint16 srcChainId,  uint addressSize, bytes32 ulnAddress) public pure returns(LayerZeroPacket.Packet memory) {\n        return PacketDecoder.getPacket(payload, srcChainId, addressSize, ulnAddress);\n    }\n\n    function getPacket(bytes memory data, uint16 srcChain, uint sizeOfSrcAddress, bytes32 ulnAddress) public pure returns(LayerZeroPacket.Packet memory) {\n        return PacketDecoder.getPacket(data, srcChain, sizeOfSrcAddress, ulnAddress);\n    }\n}"
    },
    "contracts/test/TestLayerZeroPacket.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.7.6;\npragma abicoder v2;\nimport \"../utility/LayerZeroPacket.sol\";\n\ncontract TestLayerZeroPacket {\n    function testUaPayload(uint64 nonce, uint16 srcChainId, address srcAddress, uint16 dstChainId, bytes memory dstAddress, bytes memory payload) external pure returns(LayerZeroPacket.Packet memory) {\n//        bytes memory encodedPayload = abi.encodePacked(nonce, ua, _destination, _payload);\n//        emit Packet(chainId, encodedPayload);\n        bytes memory encodedPayload = abi.encodePacked(nonce, srcAddress, dstAddress, payload);\n        bytes memory fullPayload = abi.encode(dstChainId, encodedPayload);\n        return testFullPayload(fullPayload, srcChainId, 20, bytes32(0));\n    }\n\n    function testFullPayload(bytes memory payload, uint16 srcChainId,  uint addressSize, bytes32 ulnAddress) public pure returns(LayerZeroPacket.Packet memory) {\n        return LayerZeroPacket.getPacket(payload, srcChainId, addressSize, ulnAddress);\n    }\n}"
    },
    "contracts/MPTValidatorV4.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./interfaces/IValidationLibraryHelper.sol\";\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/PacketDecoder.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ninterface IUltraLightNode {\n    struct BlockData {\n        uint confirmations;\n        bytes32 data;\n    }\n\n    struct ApplicationConfiguration {\n        uint16 inboundProofLibraryVersion;\n        uint64 inboundBlockConfirmations;\n        address relayer;\n        uint16 outboundProofType;\n        uint64 outboundBlockConfirmations;\n        address oracle;\n    }\n\n    function getAppConfig(uint16 _chainId, address userApplicationAddress) external view returns (ApplicationConfiguration memory);\n    function getBlockHeaderData(address _oracle, uint16 _remoteChainId, bytes32 _lookupHash) external view returns (BlockData memory blockData);\n}\n\ninterface IStargate {\n    // Stargate objects for abi encoding / decoding\n    struct SwapObj {\n        uint256 amount;\n        uint256 eqFee;\n        uint256 eqReward;\n        uint256 lpFee;\n        uint256 protocolFee;\n        uint256 lkbRemove;\n    }\n\n    struct CreditObj {\n        uint256 credits;\n        uint256 idealBalance;\n    }\n}\n\ncontract MPTValidatorV4 is ILayerZeroValidationLibrary, IValidationLibraryHelper {\n    using RLPDecode for RLPDecode.RLPItem;\n    using RLPDecode for RLPDecode.Iterator;\n    using PacketDecoder for bytes;\n\n    uint8 public utilsVersion = 3;\n    bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n    address immutable public stargateBridgeAddress;\n    address immutable public stgTokenAddress;\n    uint16 immutable public localChainId;\n    IUltraLightNode immutable public uln;\n\n    constructor (address _stargateBridgeAddress, address _stgTokenAddress, uint16 _localChainId, address _ulnAddress) {\n        stargateBridgeAddress = _stargateBridgeAddress;\n        stgTokenAddress = _stgTokenAddress;\n        localChainId = _localChainId;\n        uln = IUltraLightNode(_ulnAddress);\n    }\n\n    function validateProof(bytes32 _receiptsRoot, bytes calldata _transactionProof, uint _remoteAddressSize) external view override returns (LayerZeroPacket.Packet memory) {\n        require(_remoteAddressSize > 0, \"ProofLib: invalid address size\");\n\n        (uint16 remoteChainId, bytes32 blockHash, bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(_transactionProof, (uint16, bytes32, bytes[], uint[], uint));\n\n        ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n        require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n        LayerZeroPacket.Packet memory packet = log.data.getPacket(remoteChainId, _remoteAddressSize, log.contractAddress);\n\n        _assertMessagePath(packet, blockHash, _receiptsRoot);\n\n        if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n\n        if (packet.dstAddress == stgTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n        return packet;\n    }\n\n    function _assertMessagePath(LayerZeroPacket.Packet memory packet, bytes32 blockHash, bytes32 receiptsRoot) internal view {\n        require(packet.dstChainId == localChainId, \"ProofLib: invalid destination chain ID\");\n\n        IUltraLightNode.ApplicationConfiguration memory appConfig = uln.getAppConfig(packet.srcChainId, packet.dstAddress);\n        IUltraLightNode.BlockData memory blockData = uln.getBlockHeaderData(appConfig.oracle, packet.srcChainId, blockHash);\n\n        require(blockData.data == receiptsRoot, \"ProofLib: invalid receipt root\");\n\n        require(blockData.confirmations >= appConfig.inboundBlockConfirmations, \"ProofLib: not enough block confirmations\");\n    }\n\n    function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n        (bytes memory toAddressBytes, uint256 qty) = abi.decode(_payload, (bytes, uint256));\n\n        address toAddress = address(0);\n        if (toAddressBytes.length > 0) {\n            assembly { toAddress := mload(add(toAddressBytes, 20))}\n        }\n\n        if (toAddress == address(0)) {\n            address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n            bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n            return abi.encode(newToAddressBytes, qty);\n        }\n\n        // default to return the original payload\n        return _payload;\n    }\n\n    function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n        // functionType is uint8 even though the encoding will take up the side of uint256\n        uint8 functionType;\n        assembly { functionType := mload(add(_payload, 32)) }\n\n        // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n        // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n        // thus we do not care about the other type functions even if the toAddress is overly long.\n        if (functionType == 1) {\n            // decode the _payload with its types\n            (\n                ,\n                uint256 srcPoolId,\n                uint256 dstPoolId,\n                uint256 dstGasForCall,\n                IStargate.CreditObj memory c,\n                IStargate.SwapObj memory s,\n                bytes memory toAddressBytes,\n                bytes memory contractCallPayload\n            ) = abi.decode(_payload, (uint8, uint256, uint256, uint256, IStargate.CreditObj, IStargate.SwapObj, bytes, bytes));\n\n            // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n            if (contractCallPayload.length > 0) {\n                // otherwise, need to check if the payload can be delivered to the toAddress\n                address toAddress = address(0);\n                if (toAddressBytes.length > 0) {\n                    assembly { toAddress := mload(add(toAddressBytes, 20)) }\n                }\n\n                // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n                // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n                uint size;\n                assembly { size := extcodesize(toAddress) }\n\n                if (size == 0) {\n                    // size == 0 indicates its not a contract, payload wont be delivered\n                    // secure the _payload to make sure funds can be delivered to the toAddress\n                    bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n                    bytes memory securePayload = abi.encode(functionType, srcPoolId, dstPoolId, dstGasForCall, c, s, newToAddressBytes, bytes(\"\"));\n                    return securePayload;\n                }\n            }\n        }\n\n        // default to return the original payload\n        return _payload;\n    }\n\n    function secureStgTokenPayload(bytes memory _payload) external pure returns(bytes memory) {\n        return _secureStgTokenPayload(_payload);\n    }\n\n    function secureStgPayload(bytes memory _payload) external view returns(bytes memory) {\n        return _secureStgPayload(_payload);\n    }\n\n    function _getVerifiedLog(bytes32 hashRoot, uint[] memory paths, uint logIndex, bytes[] memory proof) internal pure returns(ULNLog memory) {\n        require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n        require(proof.length >0, \"ProofLib: proof size must > 0\");\n        RLPDecode.RLPItem memory item;\n        bytes memory proofBytes;\n\n        for (uint i = 0; i < proof.length; i++) {\n            proofBytes = proof[i];\n            require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n            item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n            if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n        }\n\n        // burning status + gasUsed + logBloom\n        RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n        RLPDecode.Iterator memory it =  logItem.safeGetItemByIndex(logIndex).iterator();\n        ULNLog memory log;\n        log.contractAddress = bytes32(it.next().toUint());\n        log.topicZeroSig = bytes32(it.next().safeGetItemByIndex(0).toUint());\n        log.data = it.next().toBytes();\n\n        return log;\n    }\n\n    function getUtilsVersion() external override view returns(uint8) {\n        return utilsVersion;\n    }\n\n    function getVerifyLog(bytes32 hashRoot, uint[] memory receiptSlotIndex, uint logIndex, bytes[] memory proof) external override pure returns(ULNLog memory){\n        return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n    }\n\n    function getPacket(bytes memory data, uint16 srcChain, uint sizeOfSrcAddress, bytes32 ulnAddress) external override pure returns(LayerZeroPacket.Packet memory){\n        return data.getPacket(srcChain, sizeOfSrcAddress, ulnAddress);\n    }\n\n    // profiling and test\n    function assertMessagePath(LayerZeroPacket.Packet memory packet, bytes32 blockHash, bytes32 receiptsRoot) external view {\n        _assertMessagePath(packet, blockHash, receiptsRoot);\n    }\n}\n"
    },
    "contracts/MPTValidatorStgV3.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/Buffer.sol\";\nimport \"./interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ncontract MPTValidatorStgV3 is ILayerZeroValidationLibrary {\n    using RLPDecode for RLPDecode.RLPItem;\n    using RLPDecode for RLPDecode.Iterator;\n    using Buffer for Buffer.buffer;\n    using SafeMath for uint;\n\n    bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n    address immutable public stargateBridgeAddress;\n    address immutable public stgTokenAddress;\n    uint16 immutable public localChainId;\n\n\n    constructor (address _stargateBridgeAddress, address _stgTokenAddress, uint16 _localChainId) {\n        stargateBridgeAddress = _stargateBridgeAddress;\n        stgTokenAddress = _stgTokenAddress;\n        localChainId = _localChainId;\n    }\n\n    struct ULNLog{\n        bytes32 contractAddress;\n        bytes32 topicZeroSig;\n        bytes data;\n    }\n\n    // Stargate objects for abi encoding / decoding\n    struct SwapObj {\n        uint256 amount;\n        uint256 eqFee;\n        uint256 eqReward;\n        uint256 lpFee;\n        uint256 protocolFee;\n        uint256 lkbRemove;\n    }\n\n    struct CreditObj {\n        uint256 credits;\n        uint256 idealBalance;\n    }\n\n    function validateProof(bytes32 _receiptsRoot, bytes calldata _transactionProof, uint _remoteAddressSize) external view override returns (LayerZeroPacket.Packet memory) {\n        (uint16 remoteChainId, bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(_transactionProof, (uint16, bytes[], uint[], uint));\n\n        ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n        require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n        LayerZeroPacket.Packet memory packet = _getPacket(log.data, remoteChainId, _remoteAddressSize, log.contractAddress);\n\n        require(packet.dstChainId == localChainId, \"ProofLib: invalid destination chain ID\");\n\n        if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n\n        if (packet.dstAddress == stgTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n        return packet;\n    }\n\n    function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n        (bytes memory toAddressBytes, uint256 qty) = abi.decode(_payload, (bytes, uint256));\n\n        address toAddress = address(0);\n        if (toAddressBytes.length > 0) {\n            assembly { toAddress := mload(add(toAddressBytes, 20))}\n        }\n\n        if (toAddress == address(0)) {\n            address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n            bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n            return abi.encode(newToAddressBytes, qty);\n        }\n\n        // default to return the original payload\n        return _payload;\n    }\n\n    function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n        // functionType is uint8 even though the encoding will take up the side of uint256\n        uint8 functionType;\n        assembly { functionType := mload(add(_payload, 32)) }\n\n        // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n        // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n        // thus we do not care about the other type functions even if the toAddress is overly long.\n        if (functionType == 1) {\n            // decode the _payload with its types\n            (\n                ,\n                uint256 srcPoolId,\n                uint256 dstPoolId,\n                uint256 dstGasForCall,\n                CreditObj memory c,\n                SwapObj memory s,\n                bytes memory toAddressBytes,\n                bytes memory contractCallPayload\n            ) = abi.decode(_payload, (uint8, uint256, uint256, uint256, CreditObj, SwapObj, bytes, bytes));\n\n            // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n            if (contractCallPayload.length > 0) {\n                // otherwise, need to check if the payload can be delivered to the toAddress\n                address toAddress = address(0);\n                if (toAddressBytes.length > 0) {\n                    assembly { toAddress := mload(add(toAddressBytes, 20)) }\n                }\n\n                // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n                // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n                uint size;\n                assembly { size := extcodesize(toAddress) }\n\n                if (size == 0) {\n                    // size == 0 indicates its not a contract, payload wont be delivered\n                    // secure the _payload to make sure funds can be delivered to the toAddress\n                    bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n                    bytes memory securePayload = abi.encode(functionType, srcPoolId, dstPoolId, dstGasForCall, c, s, newToAddressBytes, bytes(\"\"));\n                    return securePayload;\n                }\n            }\n        }\n\n        // default to return the original payload\n        return _payload;\n    }\n\n    function secureStgTokenPayload(bytes memory _payload) external pure returns(bytes memory) {\n        return _secureStgTokenPayload(_payload);\n    }\n\n    function secureStgPayload(bytes memory _payload) external view returns(bytes memory) {\n        return _secureStgPayload(_payload);\n    }\n\n    function _getVerifiedLog(bytes32 hashRoot, uint[] memory paths, uint logIndex, bytes[] memory proof) internal pure returns(ULNLog memory) {\n        require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n\n        RLPDecode.RLPItem memory item;\n        bytes memory proofBytes;\n\n        for (uint i = 0; i < proof.length; i++) {\n            proofBytes = proof[i];\n            require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n            item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n            if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n        }\n\n        // burning status + gasUsed + logBloom\n        RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n        RLPDecode.Iterator memory it =  logItem.safeGetItemByIndex(logIndex).iterator();\n        ULNLog memory log;\n        log.contractAddress = bytes32(it.next().toUint());\n        log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());\n        log.data = it.next().toBytes();\n\n        return log;\n    }\n\n    // profiling and test\n    function getVerifyLog(bytes32 hashRoot, uint[] memory receiptSlotIndex, uint logIndex, bytes[] memory proof) external pure returns(ULNLog memory){\n        return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n    }\n\n    function getPacket(bytes memory data, uint16 srcChain, uint sizeOfSrcAddress, bytes32 ulnAddress) external pure returns(LayerZeroPacket.Packet memory) {\n        return _getPacket(data, srcChain, sizeOfSrcAddress, ulnAddress);\n    }\n\n    function _getPacket(\n        bytes memory data,\n        uint16 srcChain,\n        uint sizeOfSrcAddress,\n        bytes32 ulnAddress\n    ) internal pure returns (LayerZeroPacket.Packet memory) {\n        uint16 dstChainId;\n        address dstAddress;\n        uint size;\n        uint64 nonce;\n\n        // The log consists of the destination chain id and then a bytes payload\n        //      0--------------------------------------------31\n        // 0   |  destination chain id\n        // 32  |  defines bytes array\n        // 64  |\n        // 96  |  bytes array size\n        // 128 |  payload\n        assembly {\n            dstChainId := mload(add(data, 32))\n            size := mload(add(data, 96)) /// size of the byte array\n            nonce := mload(add(data, 104)) // offset to convert to uint64  128  is index -24\n            dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n        }\n\n        Buffer.buffer memory srcAddressBuffer;\n        srcAddressBuffer.init(sizeOfSrcAddress);\n        srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n        uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);\n        Buffer.buffer memory payloadBuffer;\n        payloadBuffer.init(payloadSize);\n        payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n        return LayerZeroPacket.Packet(srcChain, dstChainId, nonce, dstAddress, srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);\n    }\n}\n"
    },
    "contracts/MPTValidator.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/Buffer.sol\";\nimport \"./interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ncontract MPTValidator is ILayerZeroValidationLibrary {\n    using RLPDecode for RLPDecode.RLPItem;\n    using RLPDecode for RLPDecode.Iterator;\n    using Buffer for Buffer.buffer;\n    using SafeMath for uint;\n\n    bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n    struct ULNLog{\n        bytes32 contractAddress;\n        bytes32 topicZeroSig;\n        bytes data;\n    }\n\n    function validateProof(bytes32 _receiptsRoot, bytes calldata _transactionProof, uint _remoteAddressSize) external pure override returns (LayerZeroPacket.Packet memory packet) {\n        (uint16 remoteChainId, bytes[] memory proof, uint[] memory pointers, uint receiptIndex, uint logIndex) = abi.decode(_transactionProof, (uint16, bytes[], uint[], uint, uint));\n\n        ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptIndex, logIndex, proof, pointers);\n        require(log.topicZeroSig == PACKET_SIGNATURE, \"LayerZero: packet not recognized\"); //data\n\n        return getPacket(log.data, remoteChainId, _remoteAddressSize, log.contractAddress);\n    }\n\n    function _getVerifiedLog(bytes32 hashRoot, uint receiptSlotIndex, uint logIndex, bytes[] memory proof, uint[] memory pointers) internal pure returns(ULNLog memory) {\n        // walk and assert the hash links of MPT\n        uint pointer;\n        bytes memory proofBytes;\n        for (uint i = 0; i < proof.length; i++) {\n            proofBytes = proof[i];\n            require(hashRoot == keccak256(proofBytes), \"LayerZero: invalid hashlink\");\n            if (i < pointers.length) {\n                pointer = pointers[i];\n                assembly { hashRoot := mload(add(add(proofBytes, pointer), 32)) }\n            }\n        }\n\n        // build the iterator for the proofBytes\n        RLPDecode.Iterator memory it = RLPDecode.toRlpItem(proofBytes).iterator();\n\n        // get the receipt item from either branch or leaf node\n        RLPDecode.RLPItem memory receiptItem = it.item.getItemByIndex(receiptSlotIndex);\n        // it = targetReceiptIter\n        it = receiptItem.typeOffset().iterator();\n        it.next(); // status\n        it.next(); // gasUsed\n        it.next(); // logBloom\n\n        // it = targetLogIter\n        it =  it.next().getItemByIndex(logIndex).iterator();\n        ULNLog memory log;\n        log.contractAddress = bytes32(it.next().toUint());\n        log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());\n        log.data = it.next().toBytes();\n\n        return log;\n    }\n\n    // profiling and test\n    function getVerifyLog(bytes32 hashRoot, uint receiptSlotIndex, uint logIndex, bytes[] memory proof, uint[] memory pointers) external pure returns(ULNLog memory){\n        return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof, pointers);\n    }\n\n    function getPacket(\n        bytes memory data,\n        uint16 srcChain,\n        uint sizeOfSrcAddress,\n        bytes32 ulnAddress\n    ) internal pure returns (LayerZeroPacket.Packet memory) {\n        uint16 dstChainId;\n        address dstAddress;\n        uint size;\n        uint64 nonce;\n\n        // The log consists of the destination chain id and then a bytes payload\n        //      0--------------------------------------------31\n        // 0   |  destination chain id\n        // 32  |  defines bytes array\n        // 64  |\n        // 96  |  bytes array size\n        // 128 |  payload\n        assembly {\n            dstChainId := mload(add(data, 32))\n            size := mload(add(data, 96)) /// size of the byte array\n            nonce := mload(add(data, 104)) // offset to convert to uint64  128  is index -24\n            dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n        }\n\n        Buffer.buffer memory srcAddressBuffer;\n        srcAddressBuffer.init(sizeOfSrcAddress);\n        srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n        uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);\n        Buffer.buffer memory payloadBuffer;\n        payloadBuffer.init(payloadSize);\n        payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n        return LayerZeroPacket.Packet(srcChain, dstChainId, nonce, address(dstAddress), srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf);\n    }\n}\n"
    },
    "contracts/libraries/EVMValidator.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"../MPTValidator.sol\";\n\ncontract EVMValidator is MPTValidator {}\n"
    },
    "contracts/libraries/EVMValidatorStgV3.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"../MPTValidatorStgV3.sol\";\n\ncontract EVMValidatorStgV3 is MPTValidatorStgV3 {\n    constructor (address _stargateBridgeAddress, address _stgTokenAddress, uint16 _localChainId) MPTValidatorStgV3(_stargateBridgeAddress, _stgTokenAddress, _localChainId) {}\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n    using SafeMath for uint256;\n\n    mapping (address => uint256) private _balances;\n\n    mapping (address => mapping (address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n    uint8 private _decimals;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n     * a default value of 18.\n     *\n     * To select a different value for {decimals}, use {_setupDecimals}.\n     *\n     * All three of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor (string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n        _decimals = 18;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n     * called.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return _decimals;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `recipient` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        _transfer(_msgSender(), recipient, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        _approve(_msgSender(), spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * Requirements:\n     *\n     * - `sender` and `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``sender``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n        _transfer(sender, recipient, amount);\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n        return true;\n    }\n\n    /**\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\n     *\n     * This is internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `sender` cannot be the zero address.\n     * - `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     */\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(sender, recipient, amount);\n\n        _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n        _balances[recipient] = _balances[recipient].add(amount);\n        emit Transfer(sender, recipient, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply = _totalSupply.add(amount);\n        _balances[account] = _balances[account].add(amount);\n        emit Transfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n        _totalSupply = _totalSupply.sub(amount);\n        emit Transfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Sets {decimals} to a value other than the default one of 18.\n     *\n     * WARNING: This function should only be called from the constructor. Most\n     * applications that interact with token contracts will not expect\n     * {decimals} to ever change, and may work incorrectly if it does.\n     */\n    function _setupDecimals(uint8 decimals_) internal virtual {\n        _decimals = decimals_;\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be to transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address payable) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes memory) {\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n        return msg.data;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
    },
    "contracts/test/Token.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.7.6;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract Token is ERC20 {\n    event tried();\n    event caught();\n\n    constructor() ERC20(\"test\", \"test\") {\n        _mint(msg.sender, 10_000_000_000 * 10**18);\n    }\n\n    function selfDestruct() public {\n        selfdestruct(address(0x0));\n    }\n\n    function tryCatch(address _tokenAddress) public {\n        try ERC20(_tokenAddress).totalSupply() {\n            emit tried();\n        } catch {\n            emit caught();\n        }\n    }\n}\n"
    },
    "contracts/libraries/EVMValidatorV2.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"../MPTValidatorV2.sol\";\n\ncontract EVMValidatorV2 is MPTValidatorV2 {}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 100000
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}