// Vulnerability label: UpS1
{{
  "language": "Solidity",
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 500
    },
    "debug": {
      "revertStrings": "debug"
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "abi"
        ]
      }
    }
  },
  "sources": {
    "@Keydonix/UniswapOracle.sol": {
      "content": "pragma solidity 0.6.8;\npragma experimental ABIEncoderV2;\n\nimport { BlockVerifier } from \"./BlockVerifier.sol\";\nimport { MerklePatriciaVerifier } from \"./MerklePatriciaVerifier.sol\";\nimport { Rlp } from \"./Rlp.sol\";\nimport { IUniswapV2Pair } from \"./IUniswapV2Pair.sol\";\nimport { UQ112x112 } from \"./UQ112x112.sol\";\n\ncontract UniswapOracle {\n\tusing UQ112x112 for uint224;\n\n\tbytes32 public constant reserveTimestampSlotHash = keccak256(abi.encodePacked(uint256(8)));\n\tbytes32 constant token0Slot = keccak256(abi.encodePacked(uint256(9)));\n\tbytes32 constant token1Slot = keccak256(abi.encodePacked(uint256(10)));\n\n\tstruct ProofData {\n\t\tbytes block;\n\t\tbytes accountProofNodesRlp;\n\t\tbytes reserveAndTimestampProofNodesRlp;\n\t\tbytes priceAccumulatorProofNodesRlp;\n\t}\n\n\tfunction getAccountStorageRoot(address uniswapV2Pair, ProofData memory proofData) public view returns (bytes32 storageRootHash, uint256 blockNumber, uint256 blockTimestamp) {\n\t\tbytes32 stateRoot;\n\t\t(stateRoot, blockTimestamp, blockNumber) = BlockVerifier.extractStateRootAndTimestamp(proofData.block);\n\t\tbytes memory accountDetailsBytes = MerklePatriciaVerifier.getValueFromProof(stateRoot, keccak256(abi.encodePacked(uniswapV2Pair)), proofData.accountProofNodesRlp);\n\t\tRlp.Item[] memory accountDetails = Rlp.toList(Rlp.toItem(accountDetailsBytes));\n\t\treturn (Rlp.toBytes32(accountDetails[2]), blockNumber, blockTimestamp);\n\t}\n\n\t// This function verifies the full block is old enough (MIN_BLOCK_COUNT), not too old (or blockhash will return 0x0) and return the proof values for the two storage slots we care about\n\tfunction verifyBlockAndExtractReserveData(IUniswapV2Pair uniswapV2Pair, uint8 minBlocksBack, uint8 maxBlocksBack, bytes32 slotHash, ProofData memory proofData) public view returns\n\t(uint256 blockTimestamp, uint256 blockNumber, uint256 priceCumulativeLast, uint112 reserve0, uint112 reserve1, uint256 reserveTimestamp) {\n\t\tbytes32 storageRootHash;\n\t\t(storageRootHash, blockNumber, blockTimestamp) = getAccountStorageRoot(address(uniswapV2Pair), proofData);\n\t\trequire (blockNumber <= block.number - minBlocksBack, \"Proof does not span enough blocks\");\n\t\trequire (blockNumber >= block.number - maxBlocksBack, \"Proof spans too many blocks\");\n\n\t\tpriceCumulativeLast = Rlp.rlpBytesToUint256(MerklePatriciaVerifier.getValueFromProof(storageRootHash, slotHash, proofData.priceAccumulatorProofNodesRlp));\n\t\tuint256 reserve0Reserve1TimestampPacked = Rlp.rlpBytesToUint256(MerklePatriciaVerifier.getValueFromProof(storageRootHash, reserveTimestampSlotHash, proofData.reserveAndTimestampProofNodesRlp));\n\t\treserveTimestamp = reserve0Reserve1TimestampPacked >> (112 + 112);\n\t\treserve1 = uint112((reserve0Reserve1TimestampPacked >> 112) & (2**112 - 1));\n\t\treserve0 = uint112(reserve0Reserve1TimestampPacked & (2**112 - 1));\n\t}\n\n\tfunction getPrice(IUniswapV2Pair uniswapV2Pair, address denominationToken, uint8 minBlocksBack, uint8 maxBlocksBack, ProofData memory proofData) public view returns (uint256 price, uint256 blockNumber) {\n\t\t// exchange = the ExchangeV2Pair. check denomination token (USE create2 check?!) check gas cost\n\t\tbool denominationTokenIs0;\n\t\tif (uniswapV2Pair.token0() == denominationToken) {\n\t\t\tdenominationTokenIs0 = true;\n\t\t} else if (uniswapV2Pair.token1() == denominationToken) {\n\t\t\tdenominationTokenIs0 = false;\n\t\t} else {\n\t\t\trevert(\"denominationToken invalid\");\n\t\t}\n\t\treturn getPriceRaw(uniswapV2Pair, denominationTokenIs0, minBlocksBack, maxBlocksBack, proofData);\n\t}\n\n\tfunction getPriceRaw(IUniswapV2Pair uniswapV2Pair, bool denominationTokenIs0, uint8 minBlocksBack, uint8 maxBlocksBack, ProofData memory proofData) public view returns (uint256 price, uint256 blockNumber) {\n\t\tuint256 historicBlockTimestamp;\n\t\tuint256 historicPriceCumulativeLast;\n\t\t{\n\t\t\t// Stack-too-deep workaround, manual scope\n\t\t\t// Side-note: wtf Solidity?\n\t\t\tuint112 reserve0;\n\t\t\tuint112 reserve1;\n\t\t\tuint256 reserveTimestamp;\n\t\t\t(historicBlockTimestamp, blockNumber, historicPriceCumulativeLast, reserve0, reserve1, reserveTimestamp) = verifyBlockAndExtractReserveData(uniswapV2Pair, minBlocksBack, maxBlocksBack, denominationTokenIs0 ? token1Slot : token0Slot, proofData);\n\t\t\tuint256 secondsBetweenReserveUpdateAndHistoricBlock = historicBlockTimestamp - reserveTimestamp;\n\t\t\t// bring old record up-to-date, in case there was no cumulative update in provided historic block itself\n\t\t\tif (secondsBetweenReserveUpdateAndHistoricBlock > 0) {\n\t\t\t\thistoricPriceCumulativeLast += secondsBetweenReserveUpdateAndHistoricBlock * uint(UQ112x112\n\t\t\t\t\t.encode(denominationTokenIs0 ? reserve0 : reserve1)\n\t\t\t\t\t.uqdiv(denominationTokenIs0 ? reserve1 : reserve0)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tuint256 secondsBetweenProvidedBlockAndNow = block.timestamp - historicBlockTimestamp;\n\t\tprice = (getCurrentPriceCumulativeLast(uniswapV2Pair, denominationTokenIs0) - historicPriceCumulativeLast) / secondsBetweenProvidedBlockAndNow;\n\t\treturn (price, blockNumber);\n\t}\n\n\tfunction getCurrentPriceCumulativeLast(IUniswapV2Pair uniswapV2Pair, bool denominationTokenIs0) public view returns (uint256 priceCumulativeLast) {\n\t\t(uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = uniswapV2Pair.getReserves();\n\t\tpriceCumulativeLast = denominationTokenIs0 ? uniswapV2Pair.price1CumulativeLast() : uniswapV2Pair.price0CumulativeLast();\n\t\tuint256 timeElapsed = block.timestamp - blockTimestampLast;\n\t\tpriceCumulativeLast += timeElapsed * uint(UQ112x112\n\t\t\t.encode(denominationTokenIs0 ? reserve0 : reserve1)\n\t\t\t.uqdiv(denominationTokenIs0 ? reserve1 : reserve0)\n\t\t);\n\t}\n}\n"
    },
    "@Keydonix/IUniswapV2Pair.sol": {
      "content": "pragma solidity 0.6.8;\n\ninterface IUniswapV2Pair {\n    function token0() external view returns (address);\n    function token1() external view returns (address);\n\n    function price0CumulativeLast() external view returns (uint256);\n    function price1CumulativeLast() external view returns (uint256);\n\n\tfunction getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);\n}\n"
    },
    "@Keydonix/BlockVerifier.sol": {
      "content": "pragma solidity 0.6.8;\n\nlibrary BlockVerifier {\n\tfunction extractStateRootAndTimestamp(bytes memory rlpBytes) internal view returns (bytes32 stateRoot, uint256 blockTimestamp, uint256 blockNumber) {\n\t\tassembly {\n\t\t\tfunction revertWithReason(message, length) {\n\t\t\t\tmstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n\t\t\t\tmstore(4, 0x20)\n\t\t\t\tmstore(0x24, length)\n\t\t\t\tmstore(0x44, message)\n\t\t\t\trevert(0, add(0x44, length))\n\t\t\t}\n\n\t\t\tfunction readDynamic(prefixPointer) -> dataPointer, dataLength {\n\t\t\t\tlet value := byte(0, mload(prefixPointer))\n\t\t\t\tswitch lt(value, 0x80)\n\t\t\t\tcase 1 {\n\t\t\t\t\tdataPointer := prefixPointer\n\t\t\t\t\tdataLength := 1\n\t\t\t\t}\n\t\t\t\tcase 0 {\n\t\t\t\t\tdataPointer := add(prefixPointer, 1)\n\t\t\t\t\tdataLength := sub(value, 0x80)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// get the length of the data\n\t\t\tlet rlpLength := mload(rlpBytes)\n\t\t\t// move pointer forward, ahead of length\n\t\t\trlpBytes := add(rlpBytes, 0x20)\n\n\t\t\t// we know the length of the block will be between 483 bytes and 709 bytes, which means it will have 2 length bytes after the prefix byte, so we can skip 3 bytes in\n\t\t\t// CONSIDER: we could save a trivial amount of gas by compressing most of this into a single add instruction\n\t\t\tlet parentHashPrefixPointer := add(rlpBytes, 3)\n\t\t\tlet parentHashPointer := add(parentHashPrefixPointer, 1)\n\t\t\tlet uncleHashPrefixPointer := add(parentHashPointer, 32)\n\t\t\tlet uncleHashPointer := add(uncleHashPrefixPointer, 1)\n\t\t\tlet minerAddressPrefixPointer := add(uncleHashPointer, 32)\n\t\t\tlet minerAddressPointer := add(minerAddressPrefixPointer, 1)\n\t\t\tlet stateRootPrefixPointer := add(minerAddressPointer, 20)\n\t\t\tlet stateRootPointer := add(stateRootPrefixPointer, 1)\n\t\t\tlet transactionRootPrefixPointer := add(stateRootPointer, 32)\n\t\t\tlet transactionRootPointer := add(transactionRootPrefixPointer, 1)\n\t\t\tlet receiptsRootPrefixPointer := add(transactionRootPointer, 32)\n\t\t\tlet receiptsRootPointer := add(receiptsRootPrefixPointer, 1)\n\t\t\tlet logsBloomPrefixPointer := add(receiptsRootPointer, 32)\n\t\t\tlet logsBloomPointer := add(logsBloomPrefixPointer, 3)\n\t\t\tlet difficultyPrefixPointer := add(logsBloomPointer, 256)\n\t\t\tlet difficultyPointer, difficultyLength := readDynamic(difficultyPrefixPointer)\n\t\t\tlet blockNumberPrefixPointer := add(difficultyPointer, difficultyLength)\n\t\t\tlet blockNumberPointer, blockNumberLength := readDynamic(blockNumberPrefixPointer)\n\t\t\tlet gasLimitPrefixPointer := add(blockNumberPointer, blockNumberLength)\n\t\t\tlet gasLimitPointer, gasLimitLength := readDynamic(gasLimitPrefixPointer)\n\t\t\tlet gasUsedPrefixPointer := add(gasLimitPointer, gasLimitLength)\n\t\t\tlet gasUsedPointer, gasUsedLength := readDynamic(gasUsedPrefixPointer)\n\t\t\tlet timestampPrefixPointer := add(gasUsedPointer, gasUsedLength)\n\t\t\tlet timestampPointer, timestampLength := readDynamic(timestampPrefixPointer)\n\n\t\t\tblockNumber := shr(sub(256, mul(blockNumberLength, 8)), mload(blockNumberPointer))\n\t\t\tlet blockHash := blockhash(blockNumber)\n\t\t\tlet rlpHash := keccak256(rlpBytes, rlpLength)\n\t\t\tif iszero(eq(blockHash, rlpHash)) { revertWithReason(\"blockHash != rlpHash\", 20) }\n\n\t\t\tstateRoot := mload(stateRootPointer)\n\t\t\tblockTimestamp := shr(sub(256, mul(timestampLength, 8)), mload(timestampPointer))\n\t\t}\n\t}\n}\n"
    },
    "@Keydonix/MerklePatriciaVerifier.sol": {
      "content": "pragma solidity 0.6.8;\n\nimport { Rlp } from \"./Rlp.sol\";\n\nlibrary MerklePatriciaVerifier {\n\t/*\n\t * @dev Extracts the value from a merkle proof\n\t * @param expectedRoot The expected hash of the root node of the trie.\n\t * @param path The path in the trie leading to value.\n\t * @param proofNodesRlp RLP encoded array of proof nodes.\n\t * @return The value proven to exist in the merkle patricia tree whose root is `expectedRoot` at the path `path`\n\t */\n\tfunction getValueFromProof(bytes32 expectedRoot, bytes32 path, bytes memory proofNodesRlp) internal pure returns (bytes memory) {\n\t\tRlp.Item memory rlpParentNodes = Rlp.toItem(proofNodesRlp);\n\t\tRlp.Item[] memory parentNodes = Rlp.toList(rlpParentNodes);\n\n\t\tbytes memory currentNode;\n\t\tRlp.Item[] memory currentNodeList;\n\n\t\tbytes32 nodeKey = expectedRoot;\n\t\tuint pathPtr = 0;\n\n\t\t// our input is a 32-byte path, but we have to prepend a single 0 byte to that and pass it along as a 33 byte memory array since that is what getNibbleArray wants\n\t\tbytes memory nibblePath = new bytes(33);\n\t\tassembly { mstore(add(nibblePath, 33), path) }\n\t\tnibblePath = _getNibbleArray(nibblePath);\n\n\t\trequire(path.length != 0, \"empty path provided\");\n\n\t\tcurrentNode = Rlp.toBytes(parentNodes[0]);\n\n\t\tfor (uint i=0; i<parentNodes.length; i++) {\n\t\t\trequire(pathPtr <= nibblePath.length, \"Path overflow\");\n\n\t\t\tcurrentNode = Rlp.toBytes(parentNodes[i]);\n\t\t\trequire(nodeKey == keccak256(currentNode), \"node doesn't match key\");\n\t\t\tcurrentNodeList = Rlp.toList(parentNodes[i]);\n\n\t\t\tif(currentNodeList.length == 17) {\n\t\t\t\tif(pathPtr == nibblePath.length) {\n\t\t\t\t\treturn Rlp.toData(currentNodeList[16]);\n\t\t\t\t}\n\n\t\t\t\tuint8 nextPathNibble = uint8(nibblePath[pathPtr]);\n\t\t\t\trequire(nextPathNibble <= 16, \"nibble too long\");\n\t\t\t\tnodeKey = Rlp.toBytes32(currentNodeList[nextPathNibble]);\n\t\t\t\tpathPtr += 1;\n\t\t\t} else if(currentNodeList.length == 2) {\n\t\t\t\tpathPtr += _nibblesToTraverse(Rlp.toData(currentNodeList[0]), nibblePath, pathPtr);\n\t\t\t\t// leaf node\n\t\t\t\tif(pathPtr == nibblePath.length) {\n\t\t\t\t\treturn Rlp.toData(currentNodeList[1]);\n\t\t\t\t}\n\t\t\t\t//extension node\n\t\t\t\trequire(_nibblesToTraverse(Rlp.toData(currentNodeList[0]), nibblePath, pathPtr) != 0, \"invalid extension node\");\n\n\t\t\t\tnodeKey = Rlp.toBytes32(currentNodeList[1]);\n\t\t\t} else {\n\t\t\t\trequire(false, \"unexpected length array\");\n\t\t\t}\n\t\t}\n\t\trequire(false, \"not enough proof nodes\");\n\t}\n\n\tfunction _nibblesToTraverse(bytes memory encodedPartialPath, bytes memory path, uint pathPtr) private pure returns (uint) {\n\t\tuint len;\n\t\t// encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath\n\t\t// and slicedPath have elements that are each one hex character (1 nibble)\n\t\tbytes memory partialPath = _getNibbleArray(encodedPartialPath);\n\t\tbytes memory slicedPath = new bytes(partialPath.length);\n\n\t\t// pathPtr counts nibbles in path\n\t\t// partialPath.length is a number of nibbles\n\t\tfor(uint i=pathPtr; i<pathPtr+partialPath.length; i++) {\n\t\t\tbyte pathNibble = path[i];\n\t\t\tslicedPath[i-pathPtr] = pathNibble;\n\t\t}\n\n\t\tif(keccak256(partialPath) == keccak256(slicedPath)) {\n\t\t\tlen = partialPath.length;\n\t\t} else {\n\t\t\tlen = 0;\n\t\t}\n\t\treturn len;\n\t}\n\n\t// bytes byteArray must be hp encoded\n\tfunction _getNibbleArray(bytes memory byteArray) private pure returns (bytes memory) {\n\t\tbytes memory nibbleArray;\n\t\tif (byteArray.length == 0) return nibbleArray;\n\n\t\tuint8 offset;\n\t\tuint8 hpNibble = uint8(_getNthNibbleOfBytes(0,byteArray));\n\t\tif(hpNibble == 1 || hpNibble == 3) {\n\t\t\tnibbleArray = new bytes(byteArray.length*2-1);\n\t\t\tbyte oddNibble = _getNthNibbleOfBytes(1,byteArray);\n\t\t\tnibbleArray[0] = oddNibble;\n\t\t\toffset = 1;\n\t\t} else {\n\t\t\tnibbleArray = new bytes(byteArray.length*2-2);\n\t\t\toffset = 0;\n\t\t}\n\n\t\tfor(uint i=offset; i<nibbleArray.length; i++) {\n\t\t\tnibbleArray[i] = _getNthNibbleOfBytes(i-offset+2,byteArray);\n\t\t}\n\t\treturn nibbleArray;\n\t}\n\n\tfunction _getNthNibbleOfBytes(uint n, bytes memory str) private pure returns (byte) {\n\t\treturn byte(n%2==0 ? uint8(str[n/2])/0x10 : uint8(str[n/2])%0x10);\n\t}\n}\n"
    },
    "@Keydonix/Rlp.sol": {
      "content": "pragma solidity 0.6.8;\n\nlibrary Rlp {\n\tuint constant DATA_SHORT_START = 0x80;\n\tuint constant DATA_LONG_START = 0xB8;\n\tuint constant LIST_SHORT_START = 0xC0;\n\tuint constant LIST_LONG_START = 0xF8;\n\n\tuint constant DATA_LONG_OFFSET = 0xB7;\n\tuint constant LIST_LONG_OFFSET = 0xF7;\n\n\n\tstruct Item {\n\t\tuint _unsafe_memPtr;    // Pointer to the RLP-encoded bytes.\n\t\tuint _unsafe_length;    // Number of bytes. This is the full length of the string.\n\t}\n\n\tstruct Iterator {\n\t\tItem _unsafe_item;   // Item that's being iterated over.\n\t\tuint _unsafe_nextPtr;   // Position of the next item in the list.\n\t}\n\n\t/* Iterator */\n\n\tfunction next(Iterator memory self) internal pure returns (Item memory subItem) {\n\t\trequire(hasNext(self), \"Rlp.sol:Rlp:next:1\");\n\t\tuint256 ptr = self._unsafe_nextPtr;\n\t\tuint256 itemLength = _itemLength(ptr);\n\t\tsubItem._unsafe_memPtr = ptr;\n\t\tsubItem._unsafe_length = itemLength;\n\t\tself._unsafe_nextPtr = ptr + itemLength;\n\t}\n\n\tfunction next(Iterator memory self, bool strict) internal pure returns (Item memory subItem) {\n\t\tsubItem = next(self);\n\t\trequire(!strict || _validate(subItem), \"Rlp.sol:Rlp:next:2\");\n\t}\n\n\tfunction hasNext(Iterator memory self) internal pure returns (bool) {\n\t\tRlp.Item memory item = self._unsafe_item;\n\t\treturn self._unsafe_nextPtr < item._unsafe_memPtr + item._unsafe_length;\n\t}\n\n\t/* Item */\n\n\t/// @dev Creates an Item from an array of RLP encoded bytes.\n\t/// @param self The RLP encoded bytes.\n\t/// @return An Item\n\tfunction toItem(bytes memory self) internal pure returns (Item memory) {\n\t\tuint len = self.length;\n\t\tif (len == 0) {\n\t\t\treturn Item(0, 0);\n\t\t}\n\t\tuint memPtr;\n\t\tassembly {\n\t\t\tmemPtr := add(self, 0x20)\n\t\t}\n\t\treturn Item(memPtr, len);\n\t}\n\n\t/// @dev Creates an Item from an array of RLP encoded bytes.\n\t/// @param self The RLP encoded bytes.\n\t/// @param strict Will throw if the data is not RLP encoded.\n\t/// @return An Item\n\tfunction toItem(bytes memory self, bool strict) internal pure returns (Item memory) {\n\t\tRlp.Item memory item = toItem(self);\n\t\tif(strict) {\n\t\t\tuint len = self.length;\n\t\t\trequire(_payloadOffset(item) <= len, \"Rlp.sol:Rlp:toItem4\");\n\t\t\trequire(_itemLength(item._unsafe_memPtr) == len, \"Rlp.sol:Rlp:toItem:5\");\n\t\t\trequire(_validate(item), \"Rlp.sol:Rlp:toItem:6\");\n\t\t}\n\t\treturn item;\n\t}\n\n\t/// @dev Check if the Item is null.\n\t/// @param self The Item.\n\t/// @return 'true' if the item is null.\n\tfunction isNull(Item memory self) internal pure returns (bool) {\n\t\treturn self._unsafe_length == 0;\n\t}\n\n\t/// @dev Check if the Item is a list.\n\t/// @param self The Item.\n\t/// @return 'true' if the item is a list.\n\tfunction isList(Item memory self) internal pure returns (bool) {\n\t\tif (self._unsafe_length == 0)\n\t\t\treturn false;\n\t\tuint memPtr = self._unsafe_memPtr;\n\t\tbool result;\n\t\tassembly {\n\t\t\tresult := iszero(lt(byte(0, mload(memPtr)), 0xC0))\n\t\t}\n\t\treturn result;\n\t}\n\n\t/// @dev Check if the Item is data.\n\t/// @param self The Item.\n\t/// @return 'true' if the item is data.\n\tfunction isData(Item memory self) internal pure returns (bool) {\n\t\tif (self._unsafe_length == 0)\n\t\t\treturn false;\n\t\tuint memPtr = self._unsafe_memPtr;\n\t\tbool result;\n\t\tassembly {\n\t\t\tresult := lt(byte(0, mload(memPtr)), 0xC0)\n\t\t}\n\t\treturn result;\n\t}\n\n\t/// @dev Check if the Item is empty (string or list).\n\t/// @param self The Item.\n\t/// @return result 'true' if the item is null.\n\tfunction isEmpty(Item memory self) internal pure returns (bool) {\n\t\tif(isNull(self))\n\t\t\treturn false;\n\t\tuint b0;\n\t\tuint memPtr = self._unsafe_memPtr;\n\t\tassembly {\n\t\t\tb0 := byte(0, mload(memPtr))\n\t\t}\n\t\treturn (b0 == DATA_SHORT_START || b0 == LIST_SHORT_START);\n\t}\n\n\t/// @dev Get the number of items in an RLP encoded list.\n\t/// @param self The Item.\n\t/// @return The number of items.\n\tfunction items(Item memory self) internal pure returns (uint) {\n\t\tif (!isList(self))\n\t\t\treturn 0;\n\t\tuint b0;\n\t\tuint memPtr = self._unsafe_memPtr;\n\t\tassembly {\n\t\t\tb0 := byte(0, mload(memPtr))\n\t\t}\n\t\tuint pos = memPtr + _payloadOffset(self);\n\t\tuint last = memPtr + self._unsafe_length - 1;\n\t\tuint itms;\n\t\twhile(pos <= last) {\n\t\t\tpos += _itemLength(pos);\n\t\t\titms++;\n\t\t}\n\t\treturn itms;\n\t}\n\n\t/// @dev Create an iterator.\n\t/// @param self The Item.\n\t/// @return An 'Iterator' over the item.\n\tfunction iterator(Item memory self) internal pure returns (Iterator memory) {\n\t\trequire(isList(self), \"Rlp.sol:Rlp:iterator:1\");\n\t\tuint ptr = self._unsafe_memPtr + _payloadOffset(self);\n\t\tIterator memory it;\n\t\tit._unsafe_item = self;\n\t\tit._unsafe_nextPtr = ptr;\n\t\treturn it;\n\t}\n\n\t/// @dev Return the RLP encoded bytes.\n\t/// @param self The Item.\n\t/// @return The bytes.\n\tfunction toBytes(Item memory self) internal pure returns (bytes memory) {\n\t\tuint256 len = self._unsafe_length;\n\t\trequire(len != 0, \"Rlp.sol:Rlp:toBytes:2\");\n\t\tbytes memory bts;\n\t\tbts = new bytes(len);\n\t\t_copyToBytes(self._unsafe_memPtr, bts, len);\n\t\treturn bts;\n\t}\n\n\t/// @dev Decode an Item into bytes. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toData(Item memory self) internal pure returns (bytes memory) {\n\t\trequire(isData(self));\n\t\t(uint256 rStartPos, uint256 len) = _decode(self);\n\t\tbytes memory bts;\n\t\tbts = new bytes(len);\n\t\t_copyToBytes(rStartPos, bts, len);\n\t\treturn bts;\n\t}\n\n\t/// @dev Get the list of sub-items from an RLP encoded list.\n\t/// Warning: This is inefficient, as it requires that the list is read twice.\n\t/// @param self The Item.\n\t/// @return Array of Items.\n\tfunction toList(Item memory self) internal pure returns (Item[] memory) {\n\t\trequire(isList(self), \"Rlp.sol:Rlp:toList:1\");\n\t\tuint256 numItems = items(self);\n\t\tItem[] memory list = new Item[](numItems);\n\t\tRlp.Iterator memory it = iterator(self);\n\t\tuint idx;\n\t\twhile(hasNext(it)) {\n\t\t\tlist[idx] = next(it);\n\t\t\tidx++;\n\t\t}\n\t\treturn list;\n\t}\n\n\t/// @dev Decode an Item into an ascii string. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toAscii(Item memory self) internal pure returns (string memory) {\n\t\trequire(isData(self), \"Rlp.sol:Rlp:toAscii:1\");\n\t\t(uint256 rStartPos, uint256 len) = _decode(self);\n\t\tbytes memory bts = new bytes(len);\n\t\t_copyToBytes(rStartPos, bts, len);\n\t\tstring memory str = string(bts);\n\t\treturn str;\n\t}\n\n\t/// @dev Decode an Item into a uint. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toUint(Item memory self) internal pure returns (uint) {\n\t\trequire(isData(self), \"Rlp.sol:Rlp:toUint:1\");\n\t\t(uint256 rStartPos, uint256 len) = _decode(self);\n\t\trequire(len <= 32, \"Rlp.sol:Rlp:toUint:3\");\n\t\trequire(len != 0, \"Rlp.sol:Rlp:toUint:4\");\n\t\tuint data;\n\t\tassembly {\n\t\t\tdata := div(mload(rStartPos), exp(256, sub(32, len)))\n\t\t}\n\t\treturn data;\n\t}\n\n\t/// @dev Decode an Item into a boolean. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toBool(Item memory self) internal pure returns (bool) {\n\t\trequire(isData(self), \"Rlp.sol:Rlp:toBool:1\");\n\t\t(uint256 rStartPos, uint256 len) = _decode(self);\n\t\trequire(len == 1, \"Rlp.sol:Rlp:toBool:3\");\n\t\tuint temp;\n\t\tassembly {\n\t\t\ttemp := byte(0, mload(rStartPos))\n\t\t}\n\t\trequire(temp <= 1, \"Rlp.sol:Rlp:toBool:8\");\n\t\treturn temp == 1 ? true : false;\n\t}\n\n\t/// @dev Decode an Item into a byte. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toByte(Item memory self) internal pure returns (byte) {\n\t\trequire(isData(self), \"Rlp.sol:Rlp:toByte:1\");\n\t\t(uint256 rStartPos, uint256 len) = _decode(self);\n\t\trequire(len == 1, \"Rlp.sol:Rlp:toByte:3\");\n\t\tbyte temp;\n\t\tassembly {\n\t\t\ttemp := byte(0, mload(rStartPos))\n\t\t}\n\t\treturn byte(temp);\n\t}\n\n\t/// @dev Decode an Item into an int. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toInt(Item memory self) internal pure returns (int) {\n\t\treturn int(toUint(self));\n\t}\n\n\t/// @dev Decode an Item into a bytes32. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toBytes32(Item memory self) internal pure returns (bytes32) {\n\t\treturn bytes32(toUint(self));\n\t}\n\n\t/// @dev Decode an Item into an address. This will not work if the\n\t/// Item is a list.\n\t/// @param self The Item.\n\t/// @return The decoded string.\n\tfunction toAddress(Item memory self) internal pure returns (address) {\n\t\trequire(isData(self), \"Rlp.sol:Rlp:toAddress:1\");\n\t\t(uint256 rStartPos, uint256 len) = _decode(self);\n\t\trequire(len == 20, \"Rlp.sol:Rlp:toAddress:3\");\n\t\taddress data;\n\t\tassembly {\n\t\t\tdata := div(mload(rStartPos), exp(256, 12))\n\t\t}\n\t\treturn data;\n\t}\n\n\t// Get the payload offset.\n\tfunction _payloadOffset(Item memory self) private pure returns (uint) {\n\t\tif(self._unsafe_length == 0)\n\t\t\treturn 0;\n\t\tuint b0;\n\t\tuint memPtr = self._unsafe_memPtr;\n\t\tassembly {\n\t\t\tb0 := byte(0, mload(memPtr))\n\t\t}\n\t\tif(b0 < DATA_SHORT_START)\n\t\t\treturn 0;\n\t\tif(b0 < DATA_LONG_START || (b0 >= LIST_SHORT_START && b0 < LIST_LONG_START))\n\t\t\treturn 1;\n\t\tif(b0 < LIST_SHORT_START)\n\t\t\treturn b0 - DATA_LONG_OFFSET + 1;\n\t\treturn b0 - LIST_LONG_OFFSET + 1;\n\t}\n\n\t// Get the full length of an Item.\n\tfunction _itemLength(uint memPtr) private pure returns (uint len) {\n\t\tuint b0;\n\t\tassembly {\n\t\t\tb0 := byte(0, mload(memPtr))\n\t\t}\n\t\tif (b0 < DATA_SHORT_START)\n\t\t\tlen = 1;\n\t\telse if (b0 < DATA_LONG_START)\n\t\t\tlen = b0 - DATA_SHORT_START + 1;\n\t\telse if (b0 < LIST_SHORT_START) {\n\t\t\tassembly {\n\t\t\t\tlet bLen := sub(b0, 0xB7) // bytes length (DATA_LONG_OFFSET)\n\t\t\t\tlet dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length\n\t\t\t\tlen := add(1, add(bLen, dLen)) // total length\n\t\t\t}\n\t\t}\n\t\telse if (b0 < LIST_LONG_START)\n\t\t\tlen = b0 - LIST_SHORT_START + 1;\n\t\telse {\n\t\t\tassembly {\n\t\t\t\tlet bLen := sub(b0, 0xF7) // bytes length (LIST_LONG_OFFSET)\n\t\t\t\tlet dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length\n\t\t\t\tlen := add(1, add(bLen, dLen)) // total length\n\t\t\t}\n\t\t}\n\t}\n\n\t// Get start position and length of the data.\n\tfunction _decode(Item memory self) private pure returns (uint memPtr, uint len) {\n\t\trequire(isData(self), \"Rlp.sol:Rlp:_decode:1\");\n\t\tuint b0;\n\t\tuint start = self._unsafe_memPtr;\n\t\tassembly {\n\t\t\tb0 := byte(0, mload(start))\n\t\t}\n\t\tif (b0 < DATA_SHORT_START) {\n\t\t\tmemPtr = start;\n\t\t\tlen = 1;\n\t\t\treturn (memPtr, len);\n\t\t}\n\t\tif (b0 < DATA_LONG_START) {\n\t\t\tlen = self._unsafe_length - 1;\n\t\t\tmemPtr = start + 1;\n\t\t} else {\n\t\t\tuint bLen;\n\t\t\tassembly {\n\t\t\t\tbLen := sub(b0, 0xB7) // DATA_LONG_OFFSET\n\t\t\t}\n\t\t\tlen = self._unsafe_length - 1 - bLen;\n\t\t\tmemPtr = start + bLen + 1;\n\t\t}\n\t\treturn (memPtr, len);\n\t}\n\n\t// Assumes that enough memory has been allocated to store in target.\n\tfunction _copyToBytes(uint sourceBytes, bytes memory destinationBytes, uint btsLen) internal pure {\n\t\t// Exploiting the fact that 'tgt' was the last thing to be allocated,\n\t\t// we can write entire words, and just overwrite any excess.\n\t\tassembly {\n\t\t\tlet words := div(add(btsLen, 31), 32)\n\t\t\tlet sourcePointer := sourceBytes\n\t\t\tlet destinationPointer := add(destinationBytes, 32)\n\t\t\tfor { let i := 0 } lt(i, words) { i := add(i, 1) }\n\t\t\t{\n\t\t\t\tlet offset := mul(i, 32)\n\t\t\t\tmstore(add(destinationPointer, offset), mload(add(sourcePointer, offset)))\n\t\t\t}\n\t\t\tmstore(add(destinationBytes, add(32, mload(destinationBytes))), 0)\n\t\t}\n\t}\n\n\t// Check that an Item is valid.\n\tfunction _validate(Item memory self) private pure returns (bool ret) {\n\t\t// Check that RLP is well-formed.\n\t\tuint b0;\n\t\tuint b1;\n\t\tuint memPtr = self._unsafe_memPtr;\n\t\tassembly {\n\t\t\tb0 := byte(0, mload(memPtr))\n\t\t\tb1 := byte(1, mload(memPtr))\n\t\t}\n\t\tif(b0 == DATA_SHORT_START + 1 && b1 < DATA_SHORT_START)\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tfunction rlpBytesToUint256(bytes memory source) internal pure returns (uint256 result) {\n\t\treturn Rlp.toUint(Rlp.toItem(source));\n\t}\n}\n"
    },
    "@Keydonix/UQ112x112.sol": {
      "content": "pragma solidity 0.6.8;\n\n// https://raw.githubusercontent.com/Uniswap/uniswap-v2-core/master/contracts/libraries/UQ112x112.sol\n// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))\n\n// range: [0, 2**112 - 1]\n// resolution: 1 / 2**112\n\nlibrary UQ112x112 {\n\tuint224 constant Q112 = 2**112;\n\n\t// encode a uint112 as a UQ112x112\n\tfunction encode(uint112 y) internal pure returns (uint224 z) {\n\t\tz = uint224(y) * Q112; // never overflows\n\t}\n\n\t// divide a UQ112x112 by a uint112, returning a UQ112x112\n\tfunction uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {\n\t\tz = x / uint224(y);\n\t}\n}\n"
    },
    "PriceEmitter.sol": {
      "content": "pragma solidity 0.6.8;\npragma experimental ABIEncoderV2;\n\nimport { UniswapOracle } from  '@Keydonix/UniswapOracle.sol';\nimport { IUniswapV2Pair } from \"@Keydonix/IUniswapV2Pair.sol\";\n\ncontract PriceEmitter is UniswapOracle {\n\tevent Price(uint256 price);\n\n\tfunction emitPrice(IUniswapV2Pair exchange, address denominationToken, uint8 minBlocksBack, uint8 maxBlocksBack, UniswapOracle.ProofData memory proofData) public returns (uint256 price, uint256 blockNumber) {\n\t\t(price, blockNumber) = getPrice(exchange, denominationToken, minBlocksBack, maxBlocksBack, proofData);\n\t\temit Price(price);\n\t}\n}\n"
    },
    "TestWrappers.sol": {
      "content": "pragma solidity 0.6.8;\npragma experimental ABIEncoderV2;\n\nimport { BlockVerifier } from \"@Keydonix/BlockVerifier.sol\";\nimport { MerklePatriciaVerifier } from \"@Keydonix/MerklePatriciaVerifier.sol\";\nimport { Rlp } from \"@Keydonix/Rlp.sol\";\n\ncontract BlockVerifierWrapper {\n\tfunction extractStateRootAndTimestamp(bytes memory input) public view returns (bytes32 stateRoot, uint256 blockTimestamp, uint256 blockNumber) {\n\t\treturn BlockVerifier.extractStateRootAndTimestamp(input);\n\t}\n}\ncontract MerklePatriciaVerifierWrapper {\n\tfunction getValueFromProof(bytes32 expectedRoot, bytes32 path, bytes memory proofNodesRlp) public pure returns (bytes memory) {\n\t\treturn MerklePatriciaVerifier.getValueFromProof(expectedRoot, path, proofNodesRlp);\n\t}\n}\n"
    },
    "TestErc20.sol": {
      "content": "pragma solidity 0.6.8;\n\ncontract TestErc20 {\n\tevent Transfer(address indexed from, address indexed to, uint256 value);\n\tevent Approval(address indexed owner, address indexed spender, uint256 value);\n\tmapping (address => uint256) public balanceOf;\n\tmapping (address => mapping (address => uint256)) public allowance;\n\tuint256 public totalSupply;\n\tstring public symbol;\n\tstring public name;\n\n\tconstructor(string memory _symbol, string memory _name) public {\n\t\tsymbol = _symbol;\n\t\tname = _name;\n\t}\n\tfunction kill() public {\n\t\tselfdestruct(msg.sender);\n\t}\n\tfunction mint(uint256 amount) public {\n\t\ttotalSupply += amount;\n\t\tbalanceOf[msg.sender] += amount;\n\t}\n\tfunction burn(uint256 amount) public {\n\t\trequire(balanceOf[msg.sender] >= amount);\n\t\ttotalSupply -= amount;\n\t\tbalanceOf[msg.sender] -= amount;\n\t}\n\tfunction transfer(address recipient, uint256 amount) public returns (bool) {\n\t\t_transfer(msg.sender, recipient, amount);\n\t\treturn true;\n\t}\n\tfunction approve(address spender, uint256 amount) public returns (bool) {\n\t\tallowance[msg.sender][spender] = amount;\n\t\temit Approval(msg.sender, spender, amount);\n\t\treturn true;\n\t}\n\tfunction transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {\n\t\tuint256 startingAllowance = allowance[msg.sender][sender];\n\t\trequire(startingAllowance >= amount);\n\t\tif (startingAllowance < uint256(-1)) {\n\t\t\tallowance[msg.sender][sender] = startingAllowance - amount;\n\t\t}\n\t\t_transfer(sender, recipient, amount);\n\t\treturn true;\n\t}\n\n\tfunction _transfer(address sender, address recipient, uint256 amount) internal {\n\t\trequire(balanceOf[sender] >= amount);\n\t\tbalanceOf[sender] -= amount;\n\t\tbalanceOf[recipient] += amount;\n\t\temit Transfer(sender, recipient, amount);\n\t}\n}\n"
    }
  }
}}