creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/concrete/RainterpreterParserNPE2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {IERC165, ERC165} from \"openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\n\nimport {LibParse} from \"../lib/parse/LibParse.sol\";\nimport {IParserV1} from \"rain.interpreter.interface/interface/IParserV1.sol\";\nimport {LibParseState, ParseState} from \"../lib/parse/LibParseState.sol\";\nimport {LibParseLiteral} from \"../lib/parse/literal/LibParseLiteral.sol\";\nimport {LibAllStandardOpsNP} from \"../lib/op/LibAllStandardOpsNP.sol\";\n\n/// @dev The known hash of the parser bytecode. This is used by the deployer to\n/// check that it is deploying a parser that is compatible with the interpreter.\nbytes32 constant PARSER_BYTECODE_HASH = bytes32(0xb1d7ca190b7226f62fac331b3ddad377132529d8005d2c52a5285af484823b49);\n\n/// @dev Encodes the parser meta that is used to lookup word definitions.\n/// The structure of the parser meta is:\n/// - 1 byte: The depth of the bloom filters\n/// - 1 byte: The hashing seed\n/// - The bloom filters, each is 32 bytes long, one for each build depth.\n/// - All the items for each word, each is 4 bytes long. Each item's first byte\n///   is its opcode index, the remaining 3 bytes are the word fingerprint.\n/// To do a lookup, the word is hashed with the seed, then the first byte of the\n/// hash is compared against the bloom filter. If there is a hit then we count\n/// the number of 1 bits in the bloom filter up to this item's 1 bit. We then\n/// treat this a the index of the item in the items array. We then compare the\n/// word fingerprint against the fingerprint of the item at this index. If the\n/// fingerprints equal then we have a match, else we increment the seed and try\n/// again with the next bloom filter, offsetting all the indexes by the total\n/// bit count of the previous bloom filter. If we reach the end of the bloom\n/// filters then we have a miss.\nbytes constant PARSE_META =\n    hex\"02588423482a0a64a4805a093a0046408a2000483db0020941044cd10693108128940000000000000000000800000000100000000000000000100000000000000000001f49c6a348b005fd0c1dc53744b46c3a1a6b5d512cc697651ba56d9d416380a84768119145bf1f411c9320384025b20727767586017788743d54ad3411facaed0bf793d92a5dd6b80ac51f7f13de413210b7896422844b300fd8f7982b7c1ad31611585907980f123846207d420085742d567a1d4ab12847126e57172f75b953212a4b6e332c3f7f31f3a7222e87d7c63e201236435fbbfc32e281ae25b491eb3f7af18839b31297302973c128b94d704b1ec042237d449e18a0265d3c2223f20482963a035436e60205c2140075eca1152558bb061fa22149a5e8dd144329870d6598183bbd10093462c9701ee60c073664e22009880be535267cb3269879ba1d7d424b4654aa05197e9c533ae38ebd372dd7b205e7bf522908ea4b202f3f5e0e52726c08783df917448fdb248cf8244c9232f7\";\n\n/// @dev The build depth of the parser meta.\nuint8 constant PARSE_META_BUILD_DEPTH = 2;\n\n/// @dev Every two bytes is a function pointer for an operand handler. These\n/// positional indexes all map to the same indexes looked up in the parse meta.\nbytes constant OPERAND_HANDLER_FUNCTION_POINTERS =\n    hex\"10f410f410f41189122a122a122a1189118910f410f410f4122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a122a126f1303122a126f1303122a122a122a122a122a122a122a122a122a122a122a122a122a10f413f910f413f9122a122a\";\n\n/// @dev Every two bytes is a function pointer for a literal parser. Literal\n/// dispatches are determined by the first byte(s) of the literal rather than a\n/// full word lookup, and are done with simple conditional jumps as the\n/// possibilities are limited compared to the number of words we have.\nbytes constant LITERAL_PARSER_FUNCTION_POINTERS = hex\"08860b4e0e4b0f03\";\n\n/// @title RainterpreterParserNPE2\n/// @dev The parser implementation.\ncontract RainterpreterParserNPE2 is IParserV1, ERC165 {\n    using LibParse for ParseState;\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\n        return interfaceId == type(IParserV1).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /// @inheritdoc IParserV1\n    function parse(bytes memory data) external pure virtual override returns (bytes memory, uint256[] memory) {\n        // The return is used by returning it, so this is a false positive.\n        //slither-disable-next-line unused-return\n        return LibParseState.newState(\n            data, parseMeta(), operandHandlerFunctionPointers(), literalParserFunctionPointers()\n        ).parse();\n    }\n\n    /// Virtual function to return the parse meta.\n    function parseMeta() internal pure virtual returns (bytes memory) {\n        return PARSE_META;\n    }\n\n    /// Virtual function to return the operand handler function pointers.\n    function operandHandlerFunctionPointers() internal pure virtual returns (bytes memory) {\n        return OPERAND_HANDLER_FUNCTION_POINTERS;\n    }\n\n    /// Virtual function to return the literal parser function pointers.\n    function literalParserFunctionPointers() internal pure virtual returns (bytes memory) {\n        return LITERAL_PARSER_FUNCTION_POINTERS;\n    }\n\n    /// External function to build the operand handler function pointers.\n    function buildOperandHandlerFunctionPointers() external pure returns (bytes memory) {\n        return LibAllStandardOpsNP.operandHandlerFunctionPointers();\n    }\n\n    /// External function to build the literal parser function pointers.\n    function buildLiteralParserFunctionPointers() external pure returns (bytes memory) {\n        return LibAllStandardOpsNP.literalParserFunctionPointers();\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "src/lib/parse/LibParse.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibPointer, Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {LibMemCpy} from \"rain.solmem/lib/LibMemCpy.sol\";\nimport {\n    CMASK_COMMENT_HEAD,\n    CMASK_EOS,\n    CMASK_EOL,\n    CMASK_LITERAL_HEAD,\n    CMASK_WHITESPACE,\n    CMASK_RIGHT_PAREN,\n    CMASK_LEFT_PAREN,\n    CMASK_RHS_WORD_TAIL,\n    CMASK_RHS_WORD_HEAD,\n    CMASK_LHS_RHS_DELIMITER,\n    CMASK_LHS_STACK_TAIL,\n    CMASK_LHS_STACK_HEAD,\n    COMMENT_START_SEQUENCE,\n    COMMENT_END_SEQUENCE,\n    CMASK_IDENTIFIER_HEAD\n} from \"./LibParseCMask.sol\";\nimport {LibCtPop} from \"../bitwise/LibCtPop.sol\";\nimport {LibParseMeta} from \"./LibParseMeta.sol\";\nimport {LibParseLiteral} from \"./literal/LibParseLiteral.sol\";\nimport {LibParseOperand} from \"./LibParseOperand.sol\";\nimport {Operand, OPCODE_STACK, OPCODE_UNKNOWN} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {LibParseStackName} from \"./LibParseStackName.sol\";\nimport {\n    ExcessLHSItems,\n    ExcessRHSItems,\n    NotAcceptingInputs,\n    ParseStackUnderflow,\n    ParseStackOverflow,\n    UnexpectedRHSChar,\n    UnexpectedRightParen,\n    WordSize,\n    DuplicateLHSItem,\n    ParserOutOfBounds,\n    ExpectedLeftParen,\n    UnexpectedLHSChar,\n    DanglingSource,\n    MaxSources,\n    UnclosedLeftParen,\n    MissingFinalSemi,\n    UnexpectedComment,\n    ParenOverflow,\n    UnknownWord,\n    MalformedCommentStart\n} from \"../../error/ErrParse.sol\";\nimport {\n    LibParseState,\n    ParseState,\n    FSM_YANG_MASK,\n    FSM_DEFAULT,\n    FSM_ACTIVE_SOURCE_MASK,\n    FSM_WORD_END_MASK\n} from \"./LibParseState.sol\";\nimport {LibParsePragma} from \"./LibParsePragma.sol\";\nimport {LibParseInterstitial} from \"./LibParseInterstitial.sol\";\nimport {LibParseError} from \"./LibParseError.sol\";\nimport {LibSubParse} from \"./LibSubParse.sol\";\nimport {LibBytes} from \"rain.solmem/lib/LibBytes.sol\";\nimport {LibUint256Array} from \"rain.solmem/lib/LibUint256Array.sol\";\n\nuint256 constant NOT_LOW_16_BIT_MASK = ~uint256(0xFFFF);\nuint256 constant ACTIVE_SOURCE_MASK = NOT_LOW_16_BIT_MASK;\nuint256 constant SUB_PARSER_BYTECODE_HEADER_SIZE = 5;\n\nlibrary LibParse {\n    using LibPointer for Pointer;\n    using LibParseStackName for ParseState;\n    using LibParseState for ParseState;\n    using LibParseInterstitial for ParseState;\n    using LibParseError for ParseState;\n    using LibParseMeta for ParseState;\n    using LibParsePragma for ParseState;\n    using LibParse for ParseState;\n    using LibParseOperand for ParseState;\n    using LibSubParse for ParseState;\n    using LibBytes for bytes;\n    using LibUint256Array for uint256[];\n\n    /// Parses a word that matches a tail mask between cursor and end. The caller\n    /// has several responsibilities while safely using this word.\n    /// - The caller MUST ensure that the word is not zero length.\n    ///   I.e. `end - cursor > 0`.\n    /// - The caller MUST ensure the head of the word (the first character) is\n    ///   valid according to some head mask. Generally it is expected that the\n    ///   valid chars for a head and tail may be different.\n    /// This function will extract every other character from the word, starting\n    /// with the second character, and check that it is valid according to the\n    /// tail mask. If any invalid characters are found, the parsing will stop\n    /// looping as it is assumed the remaining data is valid as something else,\n    /// just not a word.\n    function parseWord(uint256 cursor, uint256 end, uint256 mask) internal pure returns (uint256, bytes32) {\n        unchecked {\n            bytes32 word;\n            uint256 i = 1;\n            uint256 iEnd;\n            {\n                uint256 remaining = end - cursor;\n                iEnd = remaining > 0x20 ? 0x20 : remaining;\n            }\n            assembly (\"memory-safe\") {\n                // word is head + tail\n                word := mload(cursor)\n                // loop over the tail\n                //slither-disable-next-line incorrect-shift\n                for {} and(lt(i, iEnd), iszero(and(shl(byte(i, word), 1), not(mask)))) { i := add(i, 1) } {}\n\n                // zero out the rightmost part of the mload that is not the word.\n                let scrub := mul(sub(0x20, i), 8)\n                word := shl(scrub, shr(scrub, word))\n                cursor := add(cursor, i)\n            }\n            if (i == 0x20) {\n                revert WordSize(string(abi.encodePacked(word)));\n            }\n            return (cursor, word);\n        }\n    }\n\n    /// Skip an unlimited number of chars until we find one that is not in the\n    /// mask.\n    function skipMask(uint256 cursor, uint256 end, uint256 mask) internal pure returns (uint256) {\n        assembly (\"memory-safe\") {\n            //slither-disable-next-line incorrect-shift\n            for {} and(lt(cursor, end), gt(and(shl(byte(0, mload(cursor)), 1), mask), 0)) { cursor := add(cursor, 1) } {}\n        }\n        return cursor;\n    }\n\n    function parseLHS(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        unchecked {\n            while (cursor < end) {\n                bytes32 word;\n                uint256 char;\n                assembly (\"memory-safe\") {\n                    //slither-disable-next-line incorrect-shift\n                    char := shl(byte(0, mload(cursor)), 1)\n                }\n\n                if (char & CMASK_LHS_STACK_HEAD > 0) {\n                    // if yang we can't start new stack item\n                    if (state.fsm & FSM_YANG_MASK > 0) {\n                        revert UnexpectedLHSChar(state.parseErrorOffset(cursor));\n                    }\n\n                    // Named stack item.\n                    if (char & CMASK_IDENTIFIER_HEAD > 0) {\n                        (cursor, word) = parseWord(cursor, end, CMASK_LHS_STACK_TAIL);\n                        (bool exists, uint256 index) = state.pushStackName(word);\n                        (index);\n                        // If the stack name already exists, then we\n                        // revert as shadowing is not allowed.\n                        if (exists) {\n                            revert DuplicateLHSItem(state.parseErrorOffset(cursor));\n                        }\n                    }\n                    // Anon stack item.\n                    else {\n                        cursor = skipMask(cursor + 1, end, CMASK_LHS_STACK_TAIL);\n                    }\n                    // Bump the index regardless of whether the stack\n                    // item is named or not.\n                    state.topLevel1++;\n                    state.lineTracker++;\n\n                    // Set yang as we are now building a stack item.\n                    state.fsm |= FSM_YANG_MASK | FSM_ACTIVE_SOURCE_MASK;\n                } else if (char & CMASK_WHITESPACE != 0) {\n                    cursor = skipMask(cursor + 1, end, CMASK_WHITESPACE);\n                    // Set ying as we now open to possibilities.\n                    state.fsm &= ~FSM_YANG_MASK;\n                } else if (char & CMASK_LHS_RHS_DELIMITER != 0) {\n                    // Set RHS and yin.\n                    state.fsm = (state.fsm | FSM_ACTIVE_SOURCE_MASK) & ~FSM_YANG_MASK;\n                    cursor++;\n                    break;\n                } else {\n                    if (char & CMASK_COMMENT_HEAD != 0) {\n                        revert UnexpectedComment(state.parseErrorOffset(cursor));\n                    } else {\n                        revert UnexpectedLHSChar(state.parseErrorOffset(cursor));\n                    }\n                }\n            }\n            return cursor;\n        }\n    }\n\n    //slither-disable-next-line cyclomatic-complexity\n    function parseRHS(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        unchecked {\n            while (cursor < end) {\n                bytes32 word;\n                uint256 char;\n                assembly (\"memory-safe\") {\n                    //slither-disable-next-line incorrect-shift\n                    char := shl(byte(0, mload(cursor)), 1)\n                }\n\n                if (char & CMASK_RHS_WORD_HEAD > 0) {\n                    // If yang we can't start a new word.\n                    if (state.fsm & FSM_YANG_MASK > 0) {\n                        revert UnexpectedRHSChar(state.parseErrorOffset(cursor));\n                    }\n\n                    // If the word is unknown we need the cursor at the start\n                    // so that we can copy it into the subparser bytecode.\n                    uint256 cursorForUnknownWord = cursor;\n                    (cursor, word) = parseWord(cursor, end, CMASK_RHS_WORD_TAIL);\n\n                    // First check if this word is in meta.\n                    (bool exists, uint256 opcodeIndex) = state.lookupWord(word);\n                    if (exists) {\n                        cursor = state.parseOperand(cursor, end);\n                        Operand operand = state.handleOperand(opcodeIndex);\n                        state.pushOpToSource(opcodeIndex, operand);\n                        // This is a real word so we expect to see parens\n                        // after it.\n                        state.fsm |= FSM_WORD_END_MASK;\n                    }\n                    // Fallback to LHS items.\n                    else {\n                        (exists, opcodeIndex) = state.stackNameIndex(word);\n                        if (exists) {\n                            state.pushOpToSource(OPCODE_STACK, Operand.wrap(opcodeIndex));\n                            // Need to process highwater here because we\n                            // don't have any parens to open or close.\n                            state.highwater();\n                        }\n                        // Fallback to sub parsing.\n                        else {\n                            Operand operand;\n                            bytes memory subParserBytecode;\n\n                            {\n                                // Need to capture the word length up here before\n                                // we move the cursor past the operand that might\n                                // exist.\n                                uint256 wordLength = cursor - cursorForUnknownWord;\n                                uint256 subParserBytecodeLength = SUB_PARSER_BYTECODE_HEADER_SIZE + wordLength;\n                                // We store the final parsed values in the sub parser\n                                // bytecode so they can be handled as operand values,\n                                // rather than needing to be parsed as literals.\n                                // We have to move the cursor to keep the main parser\n                                // moving, but the sub parser bytecode will be\n                                // populated with the values in the state array.\n                                cursor = state.parseOperand(cursor, end);\n                                // The operand values length is only known after\n                                // parsing the operand.\n                                subParserBytecodeLength += state.operandValues.length * 0x20 + 0x20;\n\n                                // Build the bytecode that we will be sending to the\n                                // subparser. We can't yet build the byte header but\n                                // we can allocate the memory for it and move the string\n                                // tail and operand values into place.\n                                uint256 subParserBytecodeBytesLengthOffset = SUB_PARSER_BYTECODE_HEADER_SIZE;\n                                assembly (\"memory-safe\") {\n                                    subParserBytecode := mload(0x40)\n                                    // Move allocated memory past the bytes and their\n                                    // length. This is NOT an aligned allocation.\n                                    mstore(0x40, add(subParserBytecode, add(subParserBytecodeLength, 0x20)))\n                                    // Need to record the length of the unparsed\n                                    // bytes or the structure will be ambiguous to\n                                    // the sub parser.\n                                    mstore(add(subParserBytecode, subParserBytecodeBytesLengthOffset), wordLength)\n                                    mstore(subParserBytecode, subParserBytecodeLength)\n                                    // The operand of an unknown word is a pointer to\n                                    // the bytecode that needs to be sub parsed.\n                                    operand := subParserBytecode\n                                }\n                                // Copy the unknown word into the subparser bytecode\n                                // after the header bytes.\n                                LibMemCpy.unsafeCopyBytesTo(\n                                    Pointer.wrap(cursorForUnknownWord),\n                                    Pointer.wrap(\n                                        Pointer.unwrap(subParserBytecode.dataPointer())\n                                            + SUB_PARSER_BYTECODE_HEADER_SIZE\n                                    ),\n                                    wordLength\n                                );\n                            }\n                            // Copy the operand values into place for sub\n                            // parsing.\n                            {\n                                uint256 wordsToCopy = state.operandValues.length + 1;\n                                LibMemCpy.unsafeCopyWordsTo(\n                                    state.operandValues.startPointer(),\n                                    subParserBytecode.endDataPointer().unsafeSubWords(wordsToCopy),\n                                    wordsToCopy\n                                );\n                            }\n\n                            state.pushOpToSource(OPCODE_UNKNOWN, operand);\n                            // We only support words with parens for unknown words\n                            // that are sent off to the sub parsers.\n                            state.fsm |= FSM_WORD_END_MASK;\n                        }\n                    }\n\n                    state.fsm |= FSM_YANG_MASK;\n                }\n                // If this is the end of a word we MUST start a paren.\n                else if (state.fsm & FSM_WORD_END_MASK > 0) {\n                    if (char & CMASK_LEFT_PAREN == 0) {\n                        revert ExpectedLeftParen(state.parseErrorOffset(cursor));\n                    }\n                    // Increase the paren depth by 1.\n                    // i.e. move the byte offset by 3\n                    // There MAY be garbage at this new offset due to\n                    // a previous paren group being deallocated. The\n                    // deallocation process writes the input counter\n                    // to zero but leaves a garbage word in place, with\n                    // the expectation that it will be overwritten by\n                    // the next paren group.\n                    uint256 newParenOffset;\n                    assembly (\"memory-safe\") {\n                        newParenOffset := add(byte(0, mload(add(state, 0x60))), 3)\n                        mstore8(add(state, 0x60), newParenOffset)\n                    }\n                    // first 2 bytes are reserved, then remaining 62\n                    // bytes are for paren groups, so the offset MUST NOT\n                    // imply writing to the 63rd byte.\n                    if (newParenOffset > 59) {\n                        revert ParenOverflow();\n                    }\n                    cursor++;\n\n                    // We've moved past the paren, so we are no longer at\n                    // the end of a word and are yin.\n                    state.fsm &= ~(FSM_WORD_END_MASK | FSM_YANG_MASK);\n                } else if (char & CMASK_RIGHT_PAREN > 0) {\n                    uint256 parenOffset;\n                    assembly (\"memory-safe\") {\n                        parenOffset := byte(0, mload(add(state, 0x60)))\n                    }\n                    if (parenOffset == 0) {\n                        revert UnexpectedRightParen(state.parseErrorOffset(cursor));\n                    }\n                    // Decrease the paren depth by 1.\n                    // i.e. move the byte offset by -3.\n                    // This effectively deallocates the paren group, so\n                    // write the input counter out to the operand pointed\n                    // to by the pointer we deallocated.\n                    assembly (\"memory-safe\") {\n                        // State field offset.\n                        let stateOffset := add(state, 0x60)\n                        parenOffset := sub(parenOffset, 3)\n                        mstore8(stateOffset, parenOffset)\n                        mstore8(\n                            // Add 2 for the reserved bytes to the offset\n                            // then read top 16 bits from the pointer.\n                            // Add 1 to sandwitch the inputs byte between\n                            // the opcode index byte and the operand low\n                            // bytes.\n                            add(1, shr(0xf0, mload(add(add(stateOffset, 2), parenOffset)))),\n                            // Store the input counter, which is 2 bytes\n                            // after the operand write pointer.\n                            byte(0, mload(add(add(stateOffset, 4), parenOffset)))\n                        )\n                    }\n                    state.highwater();\n                    cursor++;\n                } else if (char & CMASK_WHITESPACE > 0) {\n                    cursor = skipMask(cursor + 1, end, CMASK_WHITESPACE);\n                    // Set yin as we now open to possibilities.\n                    state.fsm &= ~FSM_YANG_MASK;\n                }\n                // Handle all literals.\n                else if (char & CMASK_LITERAL_HEAD > 0) {\n                    cursor = state.pushLiteral(cursor, end);\n                    state.highwater();\n                    // We are yang now. Need the next char to release to\n                    // yin.\n                    state.fsm |= FSM_YANG_MASK;\n                } else if (char & CMASK_EOL > 0) {\n                    state.endLine(cursor);\n                    cursor++;\n                    break;\n                }\n                // End of source.\n                else if (char & CMASK_EOS > 0) {\n                    state.endLine(cursor);\n                    state.endSource();\n                    cursor++;\n\n                    state.fsm = FSM_DEFAULT;\n                    break;\n                }\n                // Comments aren't allowed in the RHS but we can give a\n                // nicer error message than the default.\n                else if (char & CMASK_COMMENT_HEAD != 0) {\n                    revert UnexpectedComment(state.parseErrorOffset(cursor));\n                } else {\n                    revert UnexpectedRHSChar(state.parseErrorOffset(cursor));\n                }\n            }\n            return cursor;\n        }\n    }\n\n    function parse(ParseState memory state) internal pure returns (bytes memory bytecode, uint256[] memory) {\n        unchecked {\n            if (state.data.length > 0) {\n                uint256 cursor;\n                uint256 end;\n                {\n                    bytes memory data = state.data;\n                    assembly (\"memory-safe\") {\n                        cursor := add(data, 0x20)\n                        end := add(cursor, mload(data))\n                    }\n                }\n                cursor = state.parseInterstitial(cursor, end);\n                cursor = state.parsePragma(cursor, end);\n                while (cursor < end) {\n                    cursor = state.parseInterstitial(cursor, end);\n                    cursor = state.parseLHS(cursor, end);\n                    cursor = state.parseRHS(cursor, end);\n                }\n                if (cursor != end) {\n                    revert ParserOutOfBounds();\n                }\n                if (state.fsm & FSM_ACTIVE_SOURCE_MASK != 0) {\n                    revert MissingFinalSemi(state.parseErrorOffset(cursor));\n                }\n            }\n            //slither-disable-next-line unused-return\n            return state.subParseWords(state.buildBytecode());\n        }\n    }\n}\n"
      },
      "lib/rain.interpreter.interface/src/interface/IParserV1.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nstruct AuthoringMeta {\n    // `word` is referenced directly in assembly so don't move the field.\n    bytes32 word;\n    uint8 operandParserOffset;\n    string description;\n}\n\n/// Identical to AuthoringMeta but without operandParserOffset.\nstruct AuthoringMetaV2 {\n    // `word` is referenced directly in assembly so don't move the field. It MUST\n    // be the first item.\n    bytes32 word;\n    string description;\n}\n\ninterface IParserV1 {\n    /// Parses a Rainlang string into an evaluable expression. MUST be\n    /// deterministic and MUST NOT have side effects. The only inputs are the\n    /// Rainlang string and the parse meta. MAY revert if the Rainlang string\n    /// is invalid. This function takes `bytes` instead of `string` to allow\n    /// for definitions of \"string\" other than UTF-8.\n    /// @param data The Rainlang bytes to parse.\n    /// @return bytecode The expressions that can be evaluated.\n    /// @return constants The constants that can be referenced by sources.\n    function parse(bytes calldata data) external pure returns (bytes calldata bytecode, uint256[] calldata constants);\n}\n"
      },
      "src/lib/parse/LibParseState.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand, OPCODE_CONSTANT} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {LibParseStackTracker, ParseStackTracker} from \"./LibParseStackTracker.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {LibMemCpy} from \"rain.solmem/lib/LibMemCpy.sol\";\nimport {\n    DanglingSource,\n    MaxSources,\n    ParseStackOverflow,\n    UnclosedLeftParen,\n    ExcessRHSItems,\n    ExcessLHSItems,\n    NotAcceptingInputs,\n    UnsupportedLiteralType,\n    InvalidSubParser,\n    OpcodeIOOverflow\n} from \"../../error/ErrParse.sol\";\nimport {LibParseLiteral} from \"./literal/LibParseLiteral.sol\";\nimport {LibParse} from \"./LibParse.sol\";\nimport {LibParseOperand} from \"./LibParseOperand.sol\";\nimport {LibParseError} from \"./LibParseError.sol\";\n\n/// @dev Initial state of an active source is just the starting offset which is\n/// 0x20.\nuint256 constant EMPTY_ACTIVE_SOURCE = 0x20;\n\nuint256 constant FSM_YANG_MASK = 1;\nuint256 constant FSM_WORD_END_MASK = 1 << 1;\nuint256 constant FSM_ACCEPTING_INPUTS_MASK = 1 << 2;\n\n/// @dev If a source is active we cannot finish parsing without a semi to trigger\n/// finalisation.\nuint256 constant FSM_ACTIVE_SOURCE_MASK = 1 << 3;\n\n/// @dev fsm default state is:\n/// - yin\n/// - not word end\n/// - accepting inputs\nuint256 constant FSM_DEFAULT = FSM_ACCEPTING_INPUTS_MASK;\n\n/// @dev The operand values array is 4 words long. In the future we could have\n/// some kind of logic that reallocates and expands this if we discover that\n/// we need more than 4 operands for a single opcode. Currently there are no\n/// opcodes in the main parser that require more than 4 operands. Of course some\n/// sub parser could implement something that expects more than 4, in which case\n/// we will have to revisit this, but it won't be a breaking change. Consider\n/// that operands in the output are only 2 bytes, so a 4 value operand array is\n/// already only allowing for 4 bits per value on average, which is pretty tight\n/// for anything other than bit flags.\nuint256 constant OPERAND_VALUES_LENGTH = 4;\n\n/// The parser is stateful. This struct keeps track of the entire state.\n/// @param activeSourcePtr The pointer to the current source being built.\n/// The active source being pointed to is:\n/// - low 16 bits: bitwise offset into the source for the next word to be\n///   written. Starts at 0x20. Once a source is no longer the active source, i.e.\n///   it is full and a member of the LL tail, the offset is replaced with a\n///   pointer to the next source (towards the head) to build a doubly linked\n///   list.\n/// - mid 16 bits: pointer to the previous active source (towards the tail). This\n///   is a linked list of sources that are built RTL and then reversed to LTR to\n///   eval.\n/// - high bits: 4 byte opcodes and operand pairs.\n/// @param sourcesBuilder A builder for the sources array. This is a 256 bit\n/// integer where each 16 bits is a literal memory pointer to a source.\n/// @param fsm The finite state machine representation of the parser.\n/// - bit 0: LHS/RHS => 0 = LHS, 1 = RHS\n/// - bit 1: yang/yin => 0 = yin, 1 = yang\n/// - bit 2: word end => 0 = not end, 1 = end\n/// - bit 3: accepting inputs => 0 = not accepting, 1 = accepting\n/// - bit 4: interstitial => 0 = not interstitial, 1 = interstitial\n/// @param topLevel0 Memory region for stack word counters. The first byte is a\n/// counter/offset into the region, which increments for every top level item\n/// parsed on the RHS. The remaining 31 bytes are the word counters for each\n/// stack item, which are incremented for every op pushed to the source. This is\n/// reset to 0 for every new source.\n/// @param topLevel1 31 additional bytes of stack words, allowing for 62 top\n/// level stack items total per source. The final byte is used to count the\n/// stack height according to the LHS for the current source. This is reset to 0\n/// for every new source.\n/// @param parenTracker0 Memory region for tracking pointers to words in the\n/// source, and counters for the number of words in each paren group. The first\n/// byte is a counter/offset into the region. The second byte is a phantom\n/// counter for the root level, the remaining 30 bytes are the paren group words.\n/// @param parenTracker1 32 additional bytes of paren group words.\n/// @param lineTracker A 32 byte memory region for tracking the current line.\n/// Will be partially reset for each line when `endLine` is called. Fully\n/// reset when a new source is started.\n/// Bytes from low to high:\n/// - byte 0: Lowest byte is the number of LHS items parsed. This is the low\n/// byte so that a simple ++ is a valid operation on the line tracker while\n/// parsing the LHS. This is reset to 0 for each new line.\n/// - byte 1: A snapshot of the first high byte of `topLevel0`, i.e. the offset\n/// of top level items as at the beginning of the line. This is reset to the high\n/// byte of `topLevel0` on each new line.\n/// - bytes 2+: A sequence of 2 byte pointers to before the start of each top\n/// level item, which is implictly after the end of the previous top level item.\n/// Allows us to quickly find the start of the RHS source for each top level\n/// item.\n/// @param stackNames A linked list of stack names. As the parser encounters\n/// named stack items it pushes them onto this linked list. The linked list is\n/// in FILO order, so the first item on the stack is the last item in the list.\n/// This makes it more efficient to reference more recent stack names on the RHS.\n/// @param literalBloom A bloom filter of all the literals that have been\n/// encountered so far. This is used to quickly dedupe literals.\n/// @param constantsBuilder A builder for the constants array.\n/// - low 16 bits: the height (length) of the constants array.\n/// - high 240 bits: a linked list of constant values. Each constant value is\n///   stored as a 256 bit key/value pair. The key is the fingerprint of the\n///   constant value, and the value is the constant value itself.\n/// @param literalParsers A 256 bit integer where each 16 bits is a function\n/// pointer to a literal parser.\nstruct ParseState {\n    /// @dev START things that are referenced directly in assembly by hardcoded\n    /// offsets. E.g.\n    /// - `pushOpToSource`\n    /// - `snapshotSourceHeadToLineTracker`\n    /// - `newSource`\n    uint256 activeSourcePtr;\n    uint256 topLevel0;\n    uint256 topLevel1;\n    uint256 parenTracker0;\n    uint256 parenTracker1;\n    uint256 lineTracker;\n    /// - `pushSubParser`\n    uint256 subParsers;\n    /// @dev END things that are referenced directly in assembly by hardcoded\n    /// offsets.\n    uint256 sourcesBuilder;\n    uint256 fsm;\n    uint256 stackNames;\n    uint256 stackNameBloom;\n    uint256 constantsBuilder;\n    uint256 constantsBloom;\n    bytes literalParsers;\n    bytes operandHandlers;\n    uint256[] operandValues;\n    ParseStackTracker stackTracker;\n    bytes data;\n    bytes meta;\n}\n\nlibrary LibParseState {\n    using LibParseState for ParseState;\n    using LibParseStackTracker for ParseStackTracker;\n    using LibParseError for ParseState;\n    using LibParseLiteral for ParseState;\n\n    function newActiveSourcePointer(uint256 oldActiveSourcePointer) internal pure returns (uint256) {\n        uint256 activeSourcePtr;\n        uint256 emptyActiveSource = EMPTY_ACTIVE_SOURCE;\n        assembly (\"memory-safe\") {\n            // The active source pointer MUST be aligned to 32 bytes because we\n            // rely on alignment to know when we have filled a source and need\n            // to create a new one, or need to jump through the linked list.\n            activeSourcePtr := and(add(mload(0x40), 0x1F), not(0x1F))\n            mstore(activeSourcePtr, or(emptyActiveSource, shl(0x10, oldActiveSourcePointer)))\n            mstore(0x40, add(activeSourcePtr, 0x20))\n\n            // The old tail head must now point back to the new tail head.\n            mstore(oldActiveSourcePointer, or(and(mload(oldActiveSourcePointer), not(0xFFFF)), activeSourcePtr))\n        }\n        return activeSourcePtr;\n    }\n\n    function resetSource(ParseState memory state) internal pure {\n        state.activeSourcePtr = newActiveSourcePointer(0);\n        state.topLevel0 = 0;\n        state.topLevel1 = 0;\n        state.parenTracker0 = 0;\n        state.parenTracker1 = 0;\n        state.lineTracker = 0;\n\n        // We don't reset sub parsers because they are global and immutable to\n        // the parsing process.\n\n        state.stackNames = 0;\n        state.stackNameBloom = 0;\n        state.stackTracker = ParseStackTracker.wrap(0);\n    }\n\n    function newState(bytes memory data, bytes memory meta, bytes memory operandHandlers, bytes memory literalParsers)\n        internal\n        pure\n        returns (ParseState memory)\n    {\n        ParseState memory state = ParseState(\n            // activeSource\n            // (will be built in `newActiveSource`)\n            0,\n            // topLevel0\n            0,\n            // topLevel1\n            0,\n            // parenTracker0\n            0,\n            // parenTracker1\n            0,\n            // lineTracker\n            // (will be built in `resetSource`)\n            0,\n            // sub parsers\n            0,\n            // sourcesBuilder\n            0,\n            // fsm\n            FSM_DEFAULT,\n            // stackNames\n            0,\n            // stackNameBloom\n            0,\n            // literalBloom\n            0,\n            // constantsBuilder\n            0,\n            // literalParsers\n            literalParsers,\n            // operandHandlers\n            operandHandlers,\n            // operandValues\n            new uint256[](OPERAND_VALUES_LENGTH),\n            // stackTracker\n            ParseStackTracker.wrap(0),\n            // data bytes\n            data,\n            // meta bytes\n            meta\n        );\n        state.resetSource();\n        return state;\n    }\n\n    function pushSubParser(ParseState memory state, uint256 cursor, uint256 subParser) internal pure {\n        if (subParser > uint256(type(uint160).max)) {\n            revert InvalidSubParser(state.parseErrorOffset(cursor));\n        }\n\n        uint256 tail = state.subParsers;\n        // Move the tail off to a new allocation.\n        uint256 tailPointer;\n        assembly (\"memory-safe\") {\n            tailPointer := mload(0x40)\n            mstore(0x40, add(tailPointer, 0x20))\n            mstore(tailPointer, tail)\n        }\n        // Put the tail pointer in the high bits of the new head.\n        state.subParsers = subParser | tailPointer << 0xF0;\n    }\n\n    // Find the pointer to the first opcode in the source LL. Put it in the line\n    // tracker at the appropriate offset.\n    function snapshotSourceHeadToLineTracker(ParseState memory state) internal pure {\n        uint256 activeSourcePtr = state.activeSourcePtr;\n        assembly (\"memory-safe\") {\n            let topLevel0Pointer := add(state, 0x20)\n            let totalRHSTopLevel := byte(0, mload(topLevel0Pointer))\n            // Only do stuff if the current word counter is zero.\n            if iszero(byte(0, mload(add(topLevel0Pointer, add(totalRHSTopLevel, 1))))) {\n                let byteOffset := div(and(mload(activeSourcePtr), 0xFFFF), 8)\n                let sourceHead := add(activeSourcePtr, sub(0x20, byteOffset))\n\n                let lineTracker := mload(add(state, 0xa0))\n                let lineRHSTopLevel := sub(totalRHSTopLevel, byte(30, lineTracker))\n                let offset := mul(0x10, add(lineRHSTopLevel, 1))\n                lineTracker := or(lineTracker, shl(offset, sourceHead))\n                mstore(add(state, 0xa0), lineTracker)\n            }\n        }\n    }\n\n    //slither-disable-next-line cyclomatic-complexity\n    function endLine(ParseState memory state, uint256 cursor) internal pure {\n        unchecked {\n            {\n                uint256 parenOffset;\n                assembly (\"memory-safe\") {\n                    parenOffset := byte(0, mload(add(state, 0x60)))\n                }\n                if (parenOffset > 0) {\n                    revert UnclosedLeftParen(state.parseErrorOffset(cursor));\n                }\n            }\n\n            // This will snapshot the current head of the source, which will be\n            // the start of where we want to read for the final line RHS item,\n            // if it exists.\n            state.snapshotSourceHeadToLineTracker();\n\n            // Preserve the accepting inputs flag but set\n            // everything else back to defaults. Also set that\n            // there is an active source.\n            state.fsm = (FSM_DEFAULT & ~FSM_ACCEPTING_INPUTS_MASK) | (state.fsm & FSM_ACCEPTING_INPUTS_MASK)\n                | FSM_ACTIVE_SOURCE_MASK;\n\n            uint256 lineLHSItems = state.lineTracker & 0xFF;\n            // Total number of RHS at top level is the top byte of topLevel0.\n            uint256 totalRHSTopLevel = state.topLevel0 >> 0xf8;\n            // Snapshot for RHS from start of line is second low byte of\n            // lineTracker.\n            uint256 lineRHSTopLevel = totalRHSTopLevel - ((state.lineTracker >> 8) & 0xFF);\n\n            // If:\n            // - we are accepting inputs\n            // - the RHS on this line is empty\n            // Then we treat the LHS items as inputs to the source. This means that\n            // we need to move the RHS offset to the end of the LHS items. There MAY\n            // be 0 LHS items, e.g. if the entire source is empty. This can only\n            // happen at the start of the source, as any RHS item immediately flips\n            // the FSM to not accepting inputs.\n            if (lineRHSTopLevel == 0) {\n                if (state.fsm & FSM_ACCEPTING_INPUTS_MASK == 0) {\n                    revert NotAcceptingInputs(state.parseErrorOffset(cursor));\n                } else {\n                    // As there are no RHS opcodes yet we can simply set topLevel0 directly.\n                    // This is the only case where we defer to the LHS to tell\n                    // us how many top level items there are.\n                    totalRHSTopLevel += lineLHSItems;\n                    state.topLevel0 = totalRHSTopLevel << 0xf8;\n\n                    // Push the inputs onto the stack tracker.\n                    state.stackTracker = state.stackTracker.pushInputs(lineLHSItems);\n                }\n            }\n            // If:\n            // - there are multiple RHS items on this line\n            // Then there must be the same number of LHS items. Multi or zero output\n            // RHS top level items are NOT supported unless they are the only RHS\n            // item on that line.\n            else if (lineRHSTopLevel > 1) {\n                if (lineLHSItems < lineRHSTopLevel) {\n                    revert ExcessRHSItems(state.parseErrorOffset(cursor));\n                } else if (lineLHSItems > lineRHSTopLevel) {\n                    revert ExcessLHSItems(state.parseErrorOffset(cursor));\n                }\n            }\n\n            // Follow pointers to the start of the RHS item.\n            uint256 topLevelOffset = 1 + totalRHSTopLevel - lineRHSTopLevel;\n            uint256 end = (0x10 * lineRHSTopLevel) + 0x20;\n            for (uint256 offset = 0x20; offset < end; offset += 0x10) {\n                uint256 itemSourceHead = (state.lineTracker >> offset) & 0xFFFF;\n                uint256 opsDepth;\n                assembly (\"memory-safe\") {\n                    opsDepth := byte(0, mload(add(state, add(0x20, topLevelOffset))))\n                }\n                for (uint256 i = 1; i <= opsDepth; i++) {\n                    {\n                        // We've hit the end of a LL item so have to jump towards the\n                        // tail to keep going. This makes the assumption that\n                        // the relevant pointers are aligned to 32 bytes, which\n                        // is handled on allocation in `newActiveSourcePointer`.\n                        if (itemSourceHead % 0x20 == 0x1c) {\n                            assembly (\"memory-safe\") {\n                                itemSourceHead := shr(0xf0, mload(itemSourceHead))\n                            }\n                        }\n                        uint256 opInputs;\n                        assembly (\"memory-safe\") {\n                            opInputs := byte(1, mload(itemSourceHead))\n                        }\n                        state.stackTracker = state.stackTracker.pop(opInputs);\n                        // Nested multi or zero output RHS items are NOT\n                        // supported. If the top level RHS item is the ONLY RHS\n                        // item on the line then it MAY have multiple or zero\n                        // outputs. In this case we defer to the LHS to tell us\n                        // how many outputs there are. If the LHS is wrong then\n                        // later integrity checks will need to flag it.\n                        uint256 opOutputs = i == opsDepth && lineRHSTopLevel == 1 ? lineLHSItems : 1;\n                        state.stackTracker = state.stackTracker.push(opOutputs);\n\n                        // Merge the op outputs and inputs into a single byte.\n                        if (opOutputs > 0x0F || opInputs > 0x0F) {\n                            revert OpcodeIOOverflow(state.parseErrorOffset(cursor));\n                        }\n                        assembly (\"memory-safe\") {\n                            mstore8(add(itemSourceHead, 1), or(shl(4, opOutputs), opInputs))\n                        }\n                    }\n                    itemSourceHead += 4;\n                }\n                topLevelOffset++;\n            }\n\n            state.lineTracker = totalRHSTopLevel << 8;\n        }\n    }\n\n    /// We potentially just closed out some group of arbitrarily nested parens\n    /// OR a lone literal value at the top level. IF we are at the top level we\n    /// move the immutable stack highwater mark forward 1 item, which moves the\n    /// RHS offset forward 1 byte to start a new word counter.\n    function highwater(ParseState memory state) internal pure {\n        uint256 parenOffset;\n        assembly (\"memory-safe\") {\n            parenOffset := byte(0, mload(add(state, 0x60)))\n        }\n        if (parenOffset == 0) {\n            uint256 newStackRHSOffset;\n            assembly (\"memory-safe\") {\n                let stackRHSOffsetPtr := add(state, 0x20)\n                newStackRHSOffset := add(byte(0, mload(stackRHSOffsetPtr)), 1)\n                mstore8(stackRHSOffsetPtr, newStackRHSOffset)\n            }\n            if (newStackRHSOffset == 0x3f) {\n                revert ParseStackOverflow();\n            }\n        }\n    }\n\n    function constantValueBloom(uint256 value) internal pure returns (uint256 bloom) {\n        return uint256(1) << (value % 256);\n    }\n\n    /// Includes a constant value in the constants linked list so that it will\n    /// appear in the final constants array.\n    function pushConstantValue(ParseState memory state, uint256 value) internal pure {\n        unchecked {\n            uint256 headPtr;\n            uint256 tailPtr = state.constantsBuilder >> 0x10;\n            assembly (\"memory-safe\") {\n                // Allocate two words.\n                headPtr := mload(0x40)\n                mstore(0x40, add(headPtr, 0x40))\n\n                // First word is the pointer to the tail of the LL.\n                mstore(headPtr, tailPtr)\n                // Second word is the value.\n                mstore(add(headPtr, 0x20), value)\n            }\n\n            // Inc the constants height by 1 and set the new head pointer.\n            state.constantsBuilder = ((state.constantsBuilder & 0xFFFF) + 1) | (headPtr << 0x10);\n\n            // Merge in the value bloom.\n            state.constantsBloom |= constantValueBloom(value);\n        }\n    }\n\n    function pushLiteral(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        unchecked {\n            uint256 constantValue;\n            bool success;\n            (success, cursor, constantValue) = state.tryParseLiteral(cursor, end);\n            // Don't continue trying to push something that we can't parse.\n            if (!success) {\n                revert UnsupportedLiteralType(state.parseErrorOffset(cursor));\n            }\n\n            // Whether the constant is a duplicate.\n            bool exists = false;\n\n            // The index of the constant in the constants builder LL. This is\n            // starting from the top of the linked list, so the final index is\n            // the height of the linked list minus this value.\n            uint256 t = 0;\n\n            // If the constant is in the bloom filter, then it MAY be a\n            // duplicate. Try to find the constant value in the linked list of\n            // constants.\n            //\n            // If the constant is NOT in the bloom filter, then it is definitely\n            // NOT a duplicate, so avoid traversing the linked list.\n            //\n            // Worst case is a false positive in the bloom filter, which means\n            // we traverse the linked list and find no match. This is O(1) for\n            // the bloom filter and O(n) for the linked list traversal.\n            if (state.constantsBloom & constantValueBloom(constantValue) != 0) {\n                uint256 tailPtr = state.constantsBuilder >> 0x10;\n                while (tailPtr != 0 && !exists) {\n                    ++t;\n                    uint256 tailValue;\n                    assembly (\"memory-safe\") {\n                        tailValue := mload(add(tailPtr, 0x20))\n                        tailPtr := mload(tailPtr)\n                    }\n                    exists = constantValue == tailValue;\n                }\n            }\n\n            // Push the constant opcode to the source.\n            // The index is either the height of the constants, if the constant\n            // is NOT a duplicate, or the height minus the index of the\n            // duplicate. This is because the final constants array is built\n            // 0 indexed from the bottom of the linked list to the top.\n            {\n                uint256 constantsHeight = state.constantsBuilder & 0xFFFF;\n                state.pushOpToSource(OPCODE_CONSTANT, Operand.wrap(exists ? constantsHeight - t : constantsHeight));\n            }\n\n            // If the literal is not a duplicate, then we need to add it to the\n            // linked list of literals so that `t` can point to it, and we can\n            // build the constants array from the values in the linked list\n            // later.\n            if (!exists) {\n                state.pushConstantValue(constantValue);\n            }\n\n            return cursor;\n        }\n    }\n\n    function pushOpToSource(ParseState memory state, uint256 opcode, Operand operand) internal pure {\n        unchecked {\n            // This might be a top level item so try to snapshot its pointer to\n            // the line tracker before writing the stack counter.\n            state.snapshotSourceHeadToLineTracker();\n\n            // As soon as we push an op to source we can no longer accept inputs.\n            state.fsm &= ~FSM_ACCEPTING_INPUTS_MASK;\n            // We also have an active source;\n            state.fsm |= FSM_ACTIVE_SOURCE_MASK;\n\n            // Increment the top level stack counter for the current top level\n            // word. MAY be setting 0 to 1 if this is the top level.\n            assembly (\"memory-safe\") {\n                // Hardcoded offset into the state struct.\n                let counterOffset := add(state, 0x20)\n                let counterPointer := add(counterOffset, add(byte(0, mload(counterOffset)), 1))\n                // Increment the counter.\n                mstore8(counterPointer, add(byte(0, mload(counterPointer)), 1))\n            }\n\n            uint256 activeSource;\n            uint256 offset;\n            uint256 activeSourcePointer = state.activeSourcePtr;\n            assembly (\"memory-safe\") {\n                activeSource := mload(activeSourcePointer)\n                // The low 16 bits of the active source is the current offset.\n                offset := and(activeSource, 0xFFFF)\n\n                // The offset is in bits so for a byte pointer we need to divide\n                // by 8, then add 4 to move to the operand low byte.\n                let inputsBytePointer := sub(add(activeSourcePointer, 0x20), add(div(offset, 8), 4))\n\n                // Increment the paren input counter. The input counter is for the paren\n                // group that is currently being built. This means the counter is for\n                // the paren group that is one level above the current paren offset.\n                // Assumes that every word has exactly 1 output, therefore the input\n                // counter always increases by 1.\n                // Hardcoded offset into the state struct.\n                let inputCounterPos := add(state, 0x60)\n                inputCounterPos :=\n                    add(\n                        add(\n                            inputCounterPos,\n                            // the offset\n                            byte(0, mload(inputCounterPos))\n                        ),\n                        // +2 for the reserved bytes -1 to move back to the counter\n                        // for the previous paren group.\n                        1\n                    )\n                // Increment the parent counter.\n                mstore8(inputCounterPos, add(byte(0, mload(inputCounterPos)), 1))\n                // Zero out the current counter.\n                mstore8(add(inputCounterPos, 3), 0)\n\n                // Write the operand low byte pointer into the paren tracker.\n                // Move 3 bytes after the input counter pos, then shift down 32\n                // bytes to accomodate the full mload.\n                let parenTrackerPointer := sub(inputCounterPos, 29)\n                mstore(parenTrackerPointer, or(and(mload(parenTrackerPointer), not(0xFFFF)), inputsBytePointer))\n            }\n\n            // We write sources RTL so they can run LTR.\n            activeSource =\n            // increment offset. We have 16 bits allocated to the offset and stop\n            // processing at 0x100 so this never overflows into the actual source\n            // data.\n            activeSource + 0x20\n            // include the operand. The operand is assumed to be 16 bits, so we shift\n            // it into the correct position.\n            | Operand.unwrap(operand) << offset\n            // include new op. The opcode is assumed to be 8 bits, so we shift it\n            // into the correct position, beyond the operand.\n            | opcode << (offset + 0x18);\n            assembly (\"memory-safe\") {\n                mstore(activeSourcePointer, activeSource)\n            }\n\n            // We have filled the current source slot. Need to create a new active\n            // source and fulfill the doubly linked list.\n            if (offset == 0xe0) {\n                state.activeSourcePtr = newActiveSourcePointer(activeSourcePointer);\n            }\n        }\n    }\n\n    function endSource(ParseState memory state) internal pure {\n        uint256 sourcesBuilder = state.sourcesBuilder;\n        uint256 offset = sourcesBuilder >> 0xf0;\n\n        // End is the number of top level words in the source, which is the\n        // byte offset index + 1.\n        uint256 end;\n        assembly (\"memory-safe\") {\n            end := add(byte(0, mload(add(state, 0x20))), 1)\n        }\n\n        if (offset == 0xf0) {\n            revert MaxSources();\n        }\n        // Follow the word counters to build the source with the correct\n        // combination of LTR and RTL words. The stack needs to be built\n        // LTR at the top level, so that as the evaluation proceeds LTR it\n        // can reference previous items in subsequent items. However, the\n        // stack is built RTL within each item, so that nested parens are\n        // evaluated correctly similar to reverse polish notation.\n        else {\n            uint256 source;\n            ParseStackTracker stackTracker = state.stackTracker;\n            uint256 cursor = state.activeSourcePtr;\n            assembly (\"memory-safe\") {\n                // find the end of the LL tail.\n                let tailPointer := and(shr(0x10, mload(cursor)), 0xFFFF)\n                for {} iszero(iszero(tailPointer)) {} {\n                    cursor := tailPointer\n                    tailPointer := and(shr(0x10, mload(cursor)), 0xFFFF)\n                }\n\n                // Move cursor to the end of the end of the LL tail item.\n                // This is 4 bytes from the end of the EVM word, to compensate\n                // for the offset and pointer positions.\n                tailPointer := cursor\n                cursor := add(cursor, 0x1C)\n                // leave space for the source prefix in the bytecode output.\n                let length := 4\n                source := mload(0x40)\n                // Move over the source 32 byte length and the 4 byte prefix.\n                let writeCursor := add(source, 0x20)\n                writeCursor := add(writeCursor, 4)\n\n                let counterCursor := add(state, 0x21)\n                for {\n                    let i := 0\n                    let wordsTotal := byte(0, mload(counterCursor))\n                    let wordsRemaining := wordsTotal\n                } lt(i, end) {\n                    i := add(i, 1)\n                    counterCursor := add(counterCursor, 1)\n                    wordsTotal := byte(0, mload(counterCursor))\n                    wordsRemaining := wordsTotal\n                } {\n                    length := add(length, mul(wordsTotal, 4))\n                    {\n                        // 4 bytes per source word.\n                        let tailItemWordsRemaining := div(sub(cursor, tailPointer), 4)\n                        // loop to the tail item that contains the start of the words\n                        // that we need to copy.\n                        for {} gt(wordsRemaining, tailItemWordsRemaining) {} {\n                            wordsRemaining := sub(wordsRemaining, tailItemWordsRemaining)\n                            tailPointer := and(mload(tailPointer), 0xFFFF)\n                            tailItemWordsRemaining := 7\n                            cursor := add(tailPointer, 0x1C)\n                        }\n                    }\n\n                    // Now the words remaining is lte the words remaining in the\n                    // tail item. Move the cursor back to the start of the words\n                    // and copy the passed over bytes to the write cursor.\n                    {\n                        let forwardTailPointer := tailPointer\n                        let size := mul(wordsRemaining, 4)\n                        cursor := sub(cursor, size)\n                        mstore(writeCursor, mload(cursor))\n                        writeCursor := add(writeCursor, size)\n\n                        // Redefine wordsRemaining to be the number of words\n                        // left to copy.\n                        wordsRemaining := sub(wordsTotal, wordsRemaining)\n                        // Move over whole tail items.\n                        for {} gt(wordsRemaining, 7) {} {\n                            wordsRemaining := sub(wordsRemaining, 7)\n                            // Follow the forward tail pointer.\n                            forwardTailPointer := and(shr(0x10, mload(forwardTailPointer)), 0xFFFF)\n                            mstore(writeCursor, mload(forwardTailPointer))\n                            writeCursor := add(writeCursor, 0x1c)\n                        }\n                        // Move over the remaining words in the tail item.\n                        if gt(wordsRemaining, 0) {\n                            forwardTailPointer := and(shr(0x10, mload(forwardTailPointer)), 0xFFFF)\n                            mstore(writeCursor, mload(forwardTailPointer))\n                            writeCursor := add(writeCursor, mul(wordsRemaining, 4))\n                        }\n                    }\n                }\n                // Store the bytes length in the source.\n                mstore(source, length)\n                // Store the opcodes length and stack tracker in the source\n                // prefix.\n                let prefixWritePointer := add(source, 4)\n                mstore(\n                    prefixWritePointer,\n                    or(\n                        and(mload(prefixWritePointer), not(0xFFFFFFFF)),\n                        or(shl(0x18, sub(div(length, 4), 1)), stackTracker)\n                    )\n                )\n\n                // Round up to the nearest 32 bytes to realign memory.\n                mstore(0x40, and(add(writeCursor, 0x1f), not(0x1f)))\n            }\n\n            //slither-disable-next-line incorrect-shift\n            state.sourcesBuilder =\n                ((offset + 0x10) << 0xf0) | (source << offset) | (sourcesBuilder & ((1 << offset) - 1));\n\n            // Reset source as we're done with this one.\n            state.fsm &= ~FSM_ACTIVE_SOURCE_MASK;\n            state.resetSource();\n        }\n    }\n\n    function buildBytecode(ParseState memory state) internal pure returns (bytes memory bytecode) {\n        unchecked {\n            uint256 sourcesBuilder = state.sourcesBuilder;\n            uint256 offsetEnd = (sourcesBuilder >> 0xf0);\n\n            // Somehow the parser state for the active source was not reset\n            // correctly, or the finalised offset is dangling. This implies that\n            // we are building the overall sources array while still trying to\n            // build one of the individual sources. This is a bug in the parser.\n            uint256 activeSource;\n            {\n                uint256 activeSourcePointer = state.activeSourcePtr;\n                assembly (\"memory-safe\") {\n                    activeSource := mload(activeSourcePointer)\n                }\n            }\n\n            if (activeSource != EMPTY_ACTIVE_SOURCE) {\n                revert DanglingSource();\n            }\n\n            uint256 cursor;\n            uint256 sourcesCount;\n            uint256 sourcesStart;\n            assembly (\"memory-safe\") {\n                cursor := mload(0x40)\n                bytecode := cursor\n                // Move past the bytecode length, we will write this at the end.\n                cursor := add(cursor, 0x20)\n\n                // First byte is the number of sources.\n                sourcesCount := div(offsetEnd, 0x10)\n                mstore8(cursor, sourcesCount)\n                cursor := add(cursor, 1)\n\n                let pointersCursor := cursor\n\n                // Skip past the pointer space. We'll back fill it.\n                // Divide offsetEnd to convert from a bit to a byte shift.\n                cursor := add(cursor, div(offsetEnd, 8))\n                sourcesStart := cursor\n\n                // Write total bytes length into bytecode. We do ths and handle\n                // the allocation in this same assembly block for memory safety\n                // for the compiler optimiser.\n                let sourcesLength := 0\n                let sourcePointers := 0\n                for { let offset := 0 } lt(offset, offsetEnd) { offset := add(offset, 0x10) } {\n                    let currentSourcePointer := and(shr(offset, sourcesBuilder), 0xFFFF)\n                    // add 4 byte prefix to the length of the sources, all as\n                    // bytes.\n                    sourcePointers := or(sourcePointers, shl(sub(0xf0, offset), sourcesLength))\n                    let currentSourceLength := mload(currentSourcePointer)\n\n                    // Put the reference source pointer and length into the\n                    // prefix so that we can use them to copy the actual data\n                    // into the bytecode.\n                    let tmpPrefix := shl(0xe0, or(shl(0x10, currentSourcePointer), currentSourceLength))\n                    mstore(add(sourcesStart, sourcesLength), tmpPrefix)\n                    sourcesLength := add(sourcesLength, currentSourceLength)\n                }\n                mstore(pointersCursor, or(mload(pointersCursor), sourcePointers))\n                mstore(bytecode, add(sourcesLength, sub(sub(sourcesStart, 0x20), bytecode)))\n\n                // Round up to the nearest 32 bytes past cursor to realign and\n                // allocate memory.\n                mstore(0x40, and(add(add(add(0x20, mload(bytecode)), bytecode), 0x1f), not(0x1f)))\n            }\n\n            // Loop over the sources and write them into the bytecode. Perhaps\n            // there is a more efficient way to do this in the future that won't\n            // cause each source to be written twice in memory.\n            for (uint256 i = 0; i < sourcesCount; i++) {\n                Pointer sourcePointer;\n                uint256 length;\n                Pointer targetPointer;\n                assembly (\"memory-safe\") {\n                    let relativePointer := and(mload(add(bytecode, add(3, mul(i, 2)))), 0xFFFF)\n                    targetPointer := add(sourcesStart, relativePointer)\n                    let tmpPrefix := mload(targetPointer)\n                    sourcePointer := add(0x20, shr(0xf0, tmpPrefix))\n                    length := and(shr(0xe0, tmpPrefix), 0xFFFF)\n                }\n                LibMemCpy.unsafeCopyBytesTo(sourcePointer, targetPointer, length);\n            }\n        }\n    }\n\n    function buildConstants(ParseState memory state) internal pure returns (uint256[] memory constants) {\n        uint256 constantsHeight = state.constantsBuilder & 0xFFFF;\n        uint256 tailPtr = state.constantsBuilder >> 0x10;\n\n        assembly (\"memory-safe\") {\n            let cursor := mload(0x40)\n            constants := cursor\n            mstore(cursor, constantsHeight)\n            let end := cursor\n            // Move the cursor to the end of the array. Write in reverse order\n            // of the linked list traversal so that the constants are built\n            // according to the stable indexes in the source from the linked\n            // list base.\n            cursor := add(cursor, mul(constantsHeight, 0x20))\n            // Allocate one word past the cursor. This will be just after the\n            // length if the constants array is empty. Otherwise it will be\n            // just after the last constant.\n            mstore(0x40, add(cursor, 0x20))\n            // It MUST be equivalent to say that the cursor is above the end,\n            // and that we are following tail pointers until they point to 0,\n            // and that the cursor is moving as far as the constants height.\n            // This is ensured by the fact that the constants height is only\n            // incremented when a new constant is added to the linked list.\n            for {} gt(cursor, end) {\n                // Next item in the linked list.\n                cursor := sub(cursor, 0x20)\n                // tail pointer in tail keys is the low 16 bits under the\n                // fingerprint, which is different from the tail pointer in\n                // the constants builder, where it sits above the constants\n                // height.\n                tailPtr := and(mload(tailPtr), 0xFFFF)\n            } {\n                // Store the values not the keys.\n                mstore(cursor, mload(add(tailPtr, 0x20)))\n            }\n        }\n    }\n}\n"
      },
      "src/lib/parse/literal/LibParseLiteral.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {\n    CMASK_E_NOTATION,\n    CMASK_HEX,\n    CMASK_LOWER_ALPHA_A_F,\n    CMASK_NUMERIC_0_9,\n    CMASK_STRING_LITERAL_HEAD,\n    CMASK_UPPER_ALPHA_A_F,\n    CMASK_LITERAL_HEX_DISPATCH,\n    CMASK_NUMERIC_LITERAL_HEAD,\n    CMASK_SUB_PARSEABLE_LITERAL_HEAD,\n    CMASK_SUB_PARSEABLE_LITERAL_END,\n    CMASK_WHITESPACE\n} from \"../LibParseCMask.sol\";\nimport {LibParse} from \"../LibParse.sol\";\n\nimport {\n    DecimalLiteralOverflow,\n    HexLiteralOverflow,\n    MalformedExponentDigits,\n    MalformedHexLiteral,\n    OddLengthHexLiteral,\n    ZeroLengthDecimal,\n    ZeroLengthHexLiteral,\n    UnsupportedLiteralType,\n    UnclosedSubParseableLiteral\n} from \"../../../error/ErrParse.sol\";\nimport {ParseState} from \"../LibParseState.sol\";\nimport {LibParseError} from \"../LibParseError.sol\";\nimport {LibParseInterstitial} from \"../LibParseInterstitial.sol\";\nimport {LibSubParse} from \"../LibSubParse.sol\";\n\nuint256 constant LITERAL_PARSERS_LENGTH = 4;\n\nuint256 constant LITERAL_PARSER_INDEX_HEX = 0;\nuint256 constant LITERAL_PARSER_INDEX_DECIMAL = 1;\nuint256 constant LITERAL_PARSER_INDEX_STRING = 2;\nuint256 constant LITERAL_PARSER_INDEX_SUB_PARSE = 3;\n\nlibrary LibParseLiteral {\n    using LibParseLiteral for ParseState;\n    using LibParseError for ParseState;\n    using LibParseLiteral for ParseState;\n    using LibParseInterstitial for ParseState;\n    using LibSubParse for ParseState;\n\n    function selectLiteralParserByIndex(ParseState memory state, uint256 index)\n        internal\n        pure\n        returns (function(ParseState memory, uint256, uint256) pure returns (uint256, uint256))\n    {\n        bytes memory literalParsers = state.literalParsers;\n        function(ParseState memory, uint256, uint256) pure returns (uint256, uint256) parser;\n        // This is NOT bounds checked because the indexes are all expected to\n        // be provided by the parser itself and not user input.\n        assembly (\"memory-safe\") {\n            parser := and(mload(add(literalParsers, add(2, mul(index, 2)))), 0xFFFF)\n        }\n        return parser;\n    }\n\n    function parseLiteral(ParseState memory state, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (uint256, uint256)\n    {\n        (bool success, uint256 newCursor, uint256 value) = tryParseLiteral(state, cursor, end);\n        if (success) {\n            return (newCursor, value);\n        } else {\n            revert UnsupportedLiteralType(state.parseErrorOffset(cursor));\n        }\n    }\n\n    function tryParseLiteral(ParseState memory state, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (bool, uint256, uint256)\n    {\n        uint256 index;\n        {\n            uint256 word;\n            uint256 head;\n            assembly (\"memory-safe\") {\n                word := mload(cursor)\n                //slither-disable-next-line incorrect-shift\n                head := shl(byte(0, word), 1)\n            }\n\n            // Figure out the literal type and dispatch to the correct parser.\n            // Probably a numeric, most things are.\n            if ((head & CMASK_NUMERIC_LITERAL_HEAD) != 0) {\n                uint256 disambiguate;\n                assembly (\"memory-safe\") {\n                    //slither-disable-next-line incorrect-shift\n                    disambiguate := shl(byte(1, word), 1)\n                }\n                // Hexadecimal literal dispatch is 0x. We can't accidentally\n                // match x0 because we already checked that the head is 0-9.\n                if ((head | disambiguate) == CMASK_LITERAL_HEX_DISPATCH) {\n                    index = LITERAL_PARSER_INDEX_HEX;\n                } else {\n                    index = LITERAL_PARSER_INDEX_DECIMAL;\n                }\n            }\n            // Could be a lil' string.\n            else if ((head & CMASK_STRING_LITERAL_HEAD) != 0) {\n                index = LITERAL_PARSER_INDEX_STRING;\n            }\n            // Or a sub parseable something.\n            else if ((head & CMASK_SUB_PARSEABLE_LITERAL_HEAD) != 0) {\n                index = LITERAL_PARSER_INDEX_SUB_PARSE;\n            }\n            // We don't know what this is.\n            else {\n                return (false, cursor, 0);\n            }\n        }\n        uint256 value;\n        (cursor, value) = state.selectLiteralParserByIndex(index)(state, cursor, end);\n        return (true, cursor, value);\n    }\n}\n"
      },
      "src/lib/op/LibAllStandardOpsNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.19;\n\nimport {BadDynamicLength} from \"../../error/ErrOpList.sol\";\nimport {LibConvert} from \"rain.lib.typecast/LibConvert.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {AuthoringMetaV2} from \"rain.interpreter.interface/interface/IParserV1.sol\";\nimport {LibIntegrityCheckNP, IntegrityCheckStateNP} from \"../integrity/LibIntegrityCheckNP.sol\";\nimport {LibInterpreterStateNP, InterpreterStateNP} from \"../state/LibInterpreterStateNP.sol\";\nimport {LibParseOperand} from \"../parse/LibParseOperand.sol\";\nimport {LibUint256Array} from \"rain.solmem/lib/LibUint256Array.sol\";\nimport {LibOpStackNP} from \"./00/LibOpStackNP.sol\";\nimport {LibOpConstantNP} from \"./00/LibOpConstantNP.sol\";\nimport {LibOpExternNP} from \"./00/LibOpExternNP.sol\";\n\nimport {LibOpBitwiseAndNP} from \"./bitwise/LibOpBitwiseAndNP.sol\";\nimport {LibOpBitwiseOrNP} from \"./bitwise/LibOpBitwiseOrNP.sol\";\nimport {LibOpCtPopNP} from \"./bitwise/LibOpCtPopNP.sol\";\nimport {LibOpDecodeBitsNP} from \"./bitwise/LibOpDecodeBitsNP.sol\";\nimport {LibOpEncodeBitsNP} from \"./bitwise/LibOpEncodeBitsNP.sol\";\nimport {LibOpShiftBitsLeftNP} from \"./bitwise/LibOpShiftBitsLeftNP.sol\";\nimport {LibOpShiftBitsRightNP} from \"./bitwise/LibOpShiftBitsRightNP.sol\";\n\nimport {LibOpCallNP} from \"./call/LibOpCallNP.sol\";\n\nimport {LibOpContextNP} from \"./context/LibOpContextNP.sol\";\n\nimport {LibOpHashNP} from \"./crypto/LibOpHashNP.sol\";\n\nimport {LibOpERC20AllowanceNP} from \"./erc20/LibOpERC20AllowanceNP.sol\";\nimport {LibOpERC20BalanceOfNP} from \"./erc20/LibOpERC20BalanceOfNP.sol\";\nimport {LibOpERC20TotalSupplyNP} from \"./erc20/LibOpERC20TotalSupplyNP.sol\";\n\nimport {LibOpERC721BalanceOfNP} from \"./erc721/LibOpERC721BalanceOfNP.sol\";\nimport {LibOpERC721OwnerOfNP} from \"./erc721/LibOpERC721OwnerOfNP.sol\";\n\nimport {LibOpERC5313OwnerNP} from \"./erc5313/LibOpERC5313OwnerNP.sol\";\n\nimport {LibOpBlockNumberNP} from \"./evm/LibOpBlockNumberNP.sol\";\nimport {LibOpChainIdNP} from \"./evm/LibOpChainIdNP.sol\";\nimport {LibOpMaxUint256NP} from \"./evm/LibOpMaxUint256NP.sol\";\nimport {LibOpTimestampNP} from \"./evm/LibOpTimestampNP.sol\";\n\nimport {LibOpAnyNP} from \"./logic/LibOpAnyNP.sol\";\nimport {LibOpConditionsNP} from \"./logic/LibOpConditionsNP.sol\";\nimport {LibOpEnsureNP} from \"./logic/LibOpEnsureNP.sol\";\nimport {LibOpEqualToNP} from \"./logic/LibOpEqualToNP.sol\";\nimport {LibOpEveryNP} from \"./logic/LibOpEveryNP.sol\";\nimport {LibOpGreaterThanNP} from \"./logic/LibOpGreaterThanNP.sol\";\nimport {LibOpGreaterThanOrEqualToNP} from \"./logic/LibOpGreaterThanOrEqualToNP.sol\";\nimport {LibOpIfNP} from \"./logic/LibOpIfNP.sol\";\nimport {LibOpIsZeroNP} from \"./logic/LibOpIsZeroNP.sol\";\nimport {LibOpLessThanNP} from \"./logic/LibOpLessThanNP.sol\";\nimport {LibOpLessThanOrEqualToNP} from \"./logic/LibOpLessThanOrEqualToNP.sol\";\n\nimport {LibOpDecimal18ExponentialGrowthNP} from \"./math/decimal18/growth/LibOpDecimal18ExponentialGrowthNP.sol\";\nimport {LibOpDecimal18LinearGrowthNP} from \"./math/decimal18/growth/LibOpDecimal18LinearGrowthNP.sol\";\nimport {LibOpDecimal18AvgNP} from \"./math/decimal18/LibOpDecimal18AvgNP.sol\";\nimport {LibOpDecimal18CeilNP} from \"./math/decimal18/LibOpDecimal18CeilNP.sol\";\nimport {LibOpDecimal18MulNP} from \"./math/decimal18/LibOpDecimal18MulNP.sol\";\nimport {LibOpDecimal18DivNP} from \"./math/decimal18/LibOpDecimal18DivNP.sol\";\nimport {LibOpDecimal18ExpNP} from \"./math/decimal18/LibOpDecimal18ExpNP.sol\";\nimport {LibOpDecimal18Exp2NP} from \"./math/decimal18/LibOpDecimal18Exp2NP.sol\";\nimport {LibOpDecimal18FloorNP} from \"./math/decimal18/LibOpDecimal18FloorNP.sol\";\nimport {LibOpDecimal18FracNP} from \"./math/decimal18/LibOpDecimal18FracNP.sol\";\nimport {LibOpDecimal18GmNP} from \"./math/decimal18/LibOpDecimal18GmNP.sol\";\nimport {LibOpDecimal18HeadroomNP} from \"./math/decimal18/LibOpDecimal18HeadroomNP.sol\";\nimport {LibOpDecimal18InvNP} from \"./math/decimal18/LibOpDecimal18InvNP.sol\";\nimport {LibOpDecimal18LnNP} from \"./math/decimal18/LibOpDecimal18LnNP.sol\";\nimport {LibOpDecimal18Log10NP} from \"./math/decimal18/LibOpDecimal18Log10NP.sol\";\nimport {LibOpDecimal18Log2NP} from \"./math/decimal18/LibOpDecimal18Log2NP.sol\";\nimport {LibOpDecimal18PowNP} from \"./math/decimal18/LibOpDecimal18PowNP.sol\";\nimport {LibOpDecimal18PowUNP} from \"./math/decimal18/LibOpDecimal18PowUNP.sol\";\nimport {LibOpDecimal18Scale18DynamicNP} from \"./math/decimal18/LibOpDecimal18Scale18DynamicNP.sol\";\nimport {LibOpDecimal18Scale18NP} from \"./math/decimal18/LibOpDecimal18Scale18NP.sol\";\nimport {LibOpDecimal18ScaleNDynamicNP} from \"./math/decimal18/LibOpDecimal18ScaleNDynamicNP.sol\";\nimport {LibOpDecimal18ScaleNNP} from \"./math/decimal18/LibOpDecimal18ScaleNNP.sol\";\nimport {LibOpDecimal18SnapToUnitNP} from \"./math/decimal18/LibOpDecimal18SnapToUnitNP.sol\";\nimport {LibOpDecimal18SqrtNP} from \"./math/decimal18/LibOpDecimal18SqrtNP.sol\";\n\nimport {LibOpIntAddNP} from \"./math/int/LibOpIntAddNP.sol\";\nimport {LibOpIntDivNP} from \"./math/int/LibOpIntDivNP.sol\";\nimport {LibOpIntExpNP} from \"./math/int/LibOpIntExpNP.sol\";\nimport {LibOpIntMaxNP} from \"./math/int/LibOpIntMaxNP.sol\";\nimport {LibOpIntMinNP} from \"./math/int/LibOpIntMinNP.sol\";\nimport {LibOpIntModNP} from \"./math/int/LibOpIntModNP.sol\";\nimport {LibOpIntMulNP} from \"./math/int/LibOpIntMulNP.sol\";\nimport {LibOpIntSubNP} from \"./math/int/LibOpIntSubNP.sol\";\n\nimport {LibOpGetNP} from \"./store/LibOpGetNP.sol\";\nimport {LibOpSetNP} from \"./store/LibOpSetNP.sol\";\n\nimport {LibParseLiteral, ParseState, LITERAL_PARSERS_LENGTH} from \"../parse/literal/LibParseLiteral.sol\";\nimport {LibParseLiteralString} from \"../parse/literal/LibParseLiteralString.sol\";\nimport {LibParseLiteralDecimal} from \"../parse/literal/LibParseLiteralDecimal.sol\";\nimport {LibParseLiteralHex} from \"../parse/literal/LibParseLiteralHex.sol\";\nimport {LibParseLiteralSubParseable} from \"../parse/literal/LibParseLiteralSubParseable.sol\";\n\n/// @dev Number of ops currently provided by `AllStandardOpsNP`.\nuint256 constant ALL_STANDARD_OPS_LENGTH = 77;\n\n/// @title LibAllStandardOpsNP\n/// @notice Every opcode available from the core repository laid out as a single\n/// array to easily build function pointers for `IInterpreterV2`.\nlibrary LibAllStandardOpsNP {\n    function authoringMetaV2() internal pure returns (bytes memory) {\n        AuthoringMetaV2 memory lengthPlaceholder;\n        AuthoringMetaV2[ALL_STANDARD_OPS_LENGTH + 1] memory wordsFixed = [\n            lengthPlaceholder,\n            // Stack, constant and extern MUST be in this order for parsing to work.\n            AuthoringMetaV2(\"stack\", \"Copies an existing value from the stack.\"),\n            AuthoringMetaV2(\"constant\", \"Copies a constant value onto the stack.\"),\n            AuthoringMetaV2(\n                \"extern\",\n                \"Calls an external contract. The operand is the index of the encoded dispatch in the constants array. The outputs are inferred from the number of LHS items.\"\n            ),\n            AuthoringMetaV2(\n                \"context\",\n                \"Copies a value from the context. The first operand is the context column and second is the context row.\"\n            ),\n            // These are all ordered according to how they appear in the file system.\n            AuthoringMetaV2(\"bitwise-and\", \"Bitwise AND the top two items on the stack.\"),\n            AuthoringMetaV2(\"bitwise-or\", \"Bitwise OR the top two items on the stack.\"),\n            AuthoringMetaV2(\"bitwise-count-ones\", \"Counts the number of binary bits set to 1 in the input.\"),\n            AuthoringMetaV2(\n                \"bitwise-decode\",\n                \"Decodes a value from a 256 bit value that was encoded with bitwise-encode. The first operand is the start bit and the second is the length.\"\n            ),\n            AuthoringMetaV2(\n                \"bitwise-encode\",\n                \"Encodes a value into a 256 bit value. The first operand is the start bit and the second is the length.\"\n            ),\n            AuthoringMetaV2(\"bitwise-shift-left\", \"Shifts the input left by the number of bits specified in the operand.\"),\n            AuthoringMetaV2(\"bitwise-shift-right\", \"Shifts the input right by the number of bits specified in the operand.\"),\n            AuthoringMetaV2(\n                \"call\",\n                \"Calls a source by index in the same Rain bytecode. The inputs to call are copied to the top of the called stack and the outputs are copied back to the calling stack according to the LHS items. The first operand is the source index.\"\n            ),\n            AuthoringMetaV2(\"hash\", \"Hashes all inputs into a single 32 byte value using keccak256.\"),\n            AuthoringMetaV2(\n                \"erc20-allowance\",\n                \"Gets the allowance of an erc20 token for an account. The first input is the token address, the second is the owner address, and the third is the spender address.\"\n            ),\n            AuthoringMetaV2(\n                \"erc20-balance-of\",\n                \"Gets the balance of an erc20 token for an account. The first input is the token address and the second is the account address.\"\n            ),\n            AuthoringMetaV2(\n                \"erc20-total-supply\", \"Gets the total supply of an erc20 token. The input is the token address.\"\n            ),\n            AuthoringMetaV2(\n                \"erc721-balance-of\",\n                \"Gets the balance of an erc721 token for an account. The first input is the token address and the second is the account address.\"\n            ),\n            AuthoringMetaV2(\n                \"erc721-owner-of\",\n                \"Gets the owner of an erc721 token. The first input is the token address and the second is the token id.\"\n            ),\n            AuthoringMetaV2(\n                \"erc5313-owner\",\n                \"Gets the owner of an erc5313 compatible contract. Note that erc5313 specifically DOES NOT do any onchain compatibility checks, so the expression author is responsible for ensuring the contract is compatible. The input is the contract address to get the owner of.\"\n            ),\n            AuthoringMetaV2(\"block-number\", \"The current block number.\"),\n            AuthoringMetaV2(\"chain-id\", \"The current chain id.\"),\n            AuthoringMetaV2(\"max-int-value\", \"The maximum possible non-negative integer value. 2^256 - 1.\"),\n            AuthoringMetaV2(\"max-decimal18-value\", \"The maximum possible 18 decimal fixed point value. roughly 1.15e77.\"),\n            AuthoringMetaV2(\"block-timestamp\", \"The current block timestamp.\"),\n            AuthoringMetaV2(\"any\", \"The first non-zero value out of all inputs, or 0 if every input is 0.\"),\n            AuthoringMetaV2(\n                \"conditions\",\n                \"Treats inputs as pairwise condition/value pairs. The first nonzero condition's value is used. If no conditions are nonzero, the expression reverts. Provide a constant nonzero value to define a fallback case. If the number of inputs is odd, the final value is used as an error string in the case that no conditions match.\"\n            ),\n            AuthoringMetaV2(\n                \"ensure\",\n                \"Reverts if the first input is 0. The second input is a string that is used as the revert reason if the first input is 0. Has 0 outputs.\"\n            ),\n            AuthoringMetaV2(\"equal-to\", \"1 if all inputs are equal, 0 otherwise.\"),\n            AuthoringMetaV2(\"every\", \"The last nonzero value out of all inputs, or 0 if any input is 0.\"),\n            AuthoringMetaV2(\"greater-than\", \"1 if the first input is greater than the second input, 0 otherwise.\"),\n            AuthoringMetaV2(\n                \"greater-than-or-equal-to\",\n                \"1 if the first input is greater than or equal to the second input, 0 otherwise.\"\n            ),\n            AuthoringMetaV2(\n                \"if\",\n                \"If the first input is nonzero, the second input is used. Otherwise, the third input is used. If is eagerly evaluated.\"\n            ),\n            AuthoringMetaV2(\"is-zero\", \"1 if the input is 0, 0 otherwise.\"),\n            AuthoringMetaV2(\"less-than\", \"1 if the first input is less than the second input, 0 otherwise.\"),\n            AuthoringMetaV2(\n                \"less-than-or-equal-to\", \"1 if the first input is less than or equal to the second input, 0 otherwise.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-exponential-growth\",\n                \"Calculates an exponential growth curve as `base(1 + rate)^t` where `base` is the initial value, `rate` is the rate of growth and `t` is units of time. Inputs in order are `base`, `rate`, and `t` respectively as decimal 18 values.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-linear-growth\",\n                \"Calculates a linear growth curve as `base + (rate * t)` where `base` is the initial value, `rate` is the rate of growth and `t` is units of time. Inputs in order are `base`, `rate`, and `t` respectively as decimal 18 values.\"\n            ),\n            AuthoringMetaV2(\"decimal18-avg\", \"18 decimal fixed point arithmetic average of two numbers.\"),\n            AuthoringMetaV2(\"decimal18-ceil\", \"18 decimal fixed point ceiling of a number.\"),\n            AuthoringMetaV2(\n                \"decimal18-div\",\n                \"Divides the first input by all other inputs as fixed point 18 decimal numbers (i.e. 'one' is 1e18). Errors if any divisor is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-exp\",\n                \"Calculates the natural exponential e^x where x is the input as a fixed point 18 decimal number (i.e. 'one' is 1e18). Errors if the exponentiation would exceed the maximum value (roughly 1.15e77).\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-exp2\",\n                \"Calculates the binary exponential 2^x where x is the input as a fixed point 18 decimal number (i.e. 'one' is 1e18). Errors if the exponentiation would exceed the maximum value (roughly 1.15e77).\"\n            ),\n            AuthoringMetaV2(\"decimal18-floor\", \"18 decimal fixed point floor of a number.\"),\n            AuthoringMetaV2(\"decimal18-frac\", \"18 decimal fixed point fractional part of a number.\"),\n            AuthoringMetaV2(\n                \"decimal18-gm\",\n                \"Calculates the geometric mean of all inputs as fixed point 18 decimal numbers (i.e. 'one' is 1e18). Errors if any input is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-headroom\",\n                \"18 decimal fixed point headroom of a number. I.e. the distance to the next whole number (1e18 - frac(x)). The headroom at any whole decimal 18 number is 1e18 (not 0).\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-inv\",\n                \"Calculates the inverse 1 / x of the input as a fixed point 18 decimal number (i.e. 'one' is 1e18). Errors if the input is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-ln\",\n                \"Calculates the natural logarithm ln(x) where x is the input as a fixed point 18 decimal number (i.e. 'one' is 1e18). Errors if the input is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-log10\",\n                \"Calculates the base 10 logarithm log10(x) where x is the input as a fixed point 18 decimal number (i.e. 'one' is 1e18). Errors if the input is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-log2\",\n                \"Calculates the base 2 logarithm log2(x) where x is the input as a fixed point 18 decimal number (i.e. 'one' is 1e18). Errors if the input is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-mul\",\n                \"Multiplies all inputs together as fixed point 18 decimal numbers (i.e. 'one' is 1e18). Errors if the multiplication exceeds the maximum value (roughly 1.15e77).\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-power\",\n                \"Raises the first input as a fixed point 18 decimal value to the power of the second input as a fixed point 18 decimal value. Errors if the exponentiation would exceed the maximum value (roughly 1.15e77).\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-power-int\",\n                \"Raises the first input as a fixed point 18 decimal value to the power of the second input as an integer.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-scale-18-dynamic\",\n                \"Scales a value from some fixed point decimal scale to 18 decimal fixed point. The first input is the scale to scale from and the second is the value to scale. The two optional operands control rounding and saturation respectively as per `decimal18-scale-18`.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-scale-18\",\n                \"Scales an input value from some fixed point decimal scale to 18 decimal fixed point. The first operand is the scale to scale from. The second (optional) operand controls rounding where 0 (default) rounds down and 1 rounds up. The third (optional) operand controls saturation where 0 (default) errors on overflow and 1 saturates at max-decimal-value.\"\n            ),\n            AuthoringMetaV2(\n                \"int-to-decimal18\",\n                \"Scales an integer value to 18 decimal fixed point, E.g. 1 becomes 1e18 and 10 becomes 1e19. Identical to `decimal18-scale-18` with an input scale of 0, but perhaps more legible. Does NOT support saturation.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-scale-n-dynamic\",\n                \"Scales an input value from 18 decimal fixed point to some other fixed point scale N. The first input is the scale to scale to and the second is the value to scale. The two optional operand controls rounding and saturation respectively as per `decimal18-scale-n`.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-scale-n\",\n                \"Scales an input value from 18 decimal fixed point to some other fixed point scale N. The first operand is the scale to scale to. The second (optional) operand controls rounding where 0 (default) rounds down and 1 rounds up. The third (optional) operand controls saturation where 0 (default) errors on overflow and 1 saturates at max-decimal-value.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-to-int\",\n                \"Scales a fixed point 18 decimal number (i.e. 'one' is 1e18) to a non-negative integer. Always floors/rounds down any fractional part to the nearest whole integer. Identical to `decimal18-scale-n` with an input scale of 0, but perhaps more legible.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-snap-to-unit\",\n                \"Rounds a fixed point 18 decimal number (i.e. 'one' is 1e18) to the nearest whole number if it is within the threshold distance from that whole number. The first input is the threshold as an 18 decimal fixed point number and the second is the value to snap to the nearest unit.\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-sqrt\",\n                \"Calculates the square root of the input as a fixed point 18 decimal number (i.e. 'one' is 1e18). Errors if the input is negative.\"\n            ),\n            // int and decimal18 add have identical implementations and point to\n            // the same function pointer. This is intentional.\n            AuthoringMetaV2(\n                \"int-add\",\n                \"Adds all inputs together as non-negative integers. Errors if the addition exceeds the maximum value (roughly 1.15e77).\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-add\",\n                \"Adds all inputs together as fixed point 18 decimal numbers (i.e. 'one' is 1e18). Errors if the addition exceeds the maximum value (roughly 1.15e77).\"\n            ),\n            AuthoringMetaV2(\n                \"int-div\",\n                \"Divides the first input by all other inputs as non-negative integers. Errors if any divisor is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"int-exp\",\n                \"Raises the first input to the power of all other inputs as non-negative integers. Errors if the exponentiation would exceed the maximum value (roughly 1.15e77).\"\n            ),\n            // int and decimal18 max have identical implementations and point to\n            // the same function pointer. This is intentional.\n            AuthoringMetaV2(\"int-max\", \"Finds the maximum value from all inputs as non-negative integers.\"),\n            AuthoringMetaV2(\n                \"decimal18-max\",\n                \"Finds the maximum value from all inputs as fixed point 18 decimal numbers (i.e. 'one' is 1e18).\"\n            ),\n            // int and decimal18 min have identical implementations and point to\n            // the same function pointer. This is intentional.\n            AuthoringMetaV2(\"int-min\", \"Finds the minimum value from all inputs as non-negative integers.\"),\n            AuthoringMetaV2(\n                \"decimal18-min\",\n                \"Finds the minimum value from all inputs as fixed point 18 decimal numbers (i.e. 'one' is 1e18).\"\n            ),\n            AuthoringMetaV2(\n                \"int-mod\",\n                \"Modulos the first input by all other inputs as non-negative integers. Errors if any divisor is zero.\"\n            ),\n            AuthoringMetaV2(\n                \"int-mul\",\n                \"Multiplies all inputs together as non-negative integers. Errors if the multiplication exceeds the maximum value (roughly 1.15e77).\"\n            ),\n            // int and decimal18 sub have identical implementations and point to\n            // the same function pointer. This is intentional.\n            AuthoringMetaV2(\n                \"int-sub\",\n                \"Subtracts all inputs from the first input as non-negative integers. The optional operand controls whether subtraction will saturate at 0. The default behaviour, and what will happen if the operand is 0, is that the word will revert if the subtraction would result in a negative value. If the operand is 1, the word will saturate at 0 (e.g. 1-2=0).\"\n            ),\n            AuthoringMetaV2(\n                \"int-saturating-sub\",\n                \"Subtracts all inputs from the first input as non-negative integers. Saturates at 0 (e.g. 1-2=0).\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-sub\",\n                \"Subtracts all inputs from the first input as fixed point 18 decimal numbers (i.e. 'one' is 1e18). The optional operand controls whether subtraction will saturate at 0. The default behaviour, and what will happen if the operand is 0, is that the word will revert if the subtraction would result in a negative value. If the operand is 1, the word will saturate at 0 (e.g. 1e18-2e18=0).\"\n            ),\n            AuthoringMetaV2(\n                \"decimal18-saturating-sub\",\n                \"Subtracts all inputs from the first input as fixed point 18 decimal numbers (i.e. 'one' is 1e18). Saturates at 0 (e.g. 1e18-2e18=0).\"\n            ),\n            AuthoringMetaV2(\"get\", \"Gets a value from storage. The first operand is the key to lookup.\"),\n            AuthoringMetaV2(\n                \"set\",\n                \"Sets a value in storage. The first operand is the key to set and the second operand is the value to set.\"\n            )\n        ];\n        AuthoringMetaV2[] memory wordsDynamic;\n        uint256 length = ALL_STANDARD_OPS_LENGTH;\n        assembly (\"memory-safe\") {\n            wordsDynamic := wordsFixed\n            mstore(wordsDynamic, length)\n        }\n        return abi.encode(wordsDynamic);\n    }\n\n    function literalParserFunctionPointers() internal pure returns (bytes memory) {\n        unchecked {\n            function (ParseState memory, uint256, uint256) pure returns (uint256, uint256) lengthPointer;\n            uint256 length = LITERAL_PARSERS_LENGTH;\n            assembly (\"memory-safe\") {\n                lengthPointer := length\n            }\n            function (ParseState memory, uint256, uint256) pure returns (uint256, uint256)[LITERAL_PARSERS_LENGTH + 1]\n                memory pointersFixed = [\n                    lengthPointer,\n                    LibParseLiteralHex.parseHex,\n                    LibParseLiteralDecimal.parseDecimal,\n                    LibParseLiteralString.parseString,\n                    LibParseLiteralSubParseable.parseSubParseable\n                ];\n            uint256[] memory pointersDynamic;\n            assembly (\"memory-safe\") {\n                pointersDynamic := pointersFixed\n            }\n            // Sanity check that the dynamic length is correct. Should be an\n            // unreachable error.\n            if (pointersDynamic.length != LITERAL_PARSERS_LENGTH) {\n                revert BadDynamicLength(pointersDynamic.length, length);\n            }\n            return LibConvert.unsafeTo16BitBytes(pointersDynamic);\n        }\n    }\n\n    function operandHandlerFunctionPointers() internal pure returns (bytes memory) {\n        unchecked {\n            function (uint256[] memory) internal pure returns (Operand) lengthPointer;\n            uint256 length = ALL_STANDARD_OPS_LENGTH;\n            assembly (\"memory-safe\") {\n                lengthPointer := length\n            }\n            function (uint256[] memory) internal pure returns (Operand)[ALL_STANDARD_OPS_LENGTH + 1] memory\n                pointersFixed = [\n                    lengthPointer,\n                    // Stack\n                    LibParseOperand.handleOperandSingleFull,\n                    // Constant\n                    LibParseOperand.handleOperandSingleFull,\n                    // Extern\n                    LibParseOperand.handleOperandSingleFull,\n                    // Context\n                    LibParseOperand.handleOperandDoublePerByteNoDefault,\n                    // Bitwise and\n                    LibParseOperand.handleOperandDisallowed,\n                    // Bitwise or\n                    LibParseOperand.handleOperandDisallowed,\n                    // Bitwise count ones\n                    LibParseOperand.handleOperandDisallowed,\n                    // Bitwise decode\n                    LibParseOperand.handleOperandDoublePerByteNoDefault,\n                    // Bitwise encode\n                    LibParseOperand.handleOperandDoublePerByteNoDefault,\n                    // Bitwise shift left\n                    LibParseOperand.handleOperandSingleFull,\n                    // Bitwise shift right\n                    LibParseOperand.handleOperandSingleFull,\n                    // Call\n                    LibParseOperand.handleOperandSingleFull,\n                    // Hash\n                    LibParseOperand.handleOperandDisallowed,\n                    // ERC20 allowance\n                    LibParseOperand.handleOperandDisallowed,\n                    // ERC20 balance of\n                    LibParseOperand.handleOperandDisallowed,\n                    // ERC20 total supply\n                    LibParseOperand.handleOperandDisallowed,\n                    // ERC721 balance of\n                    LibParseOperand.handleOperandDisallowed,\n                    // ERC721 owner of\n                    LibParseOperand.handleOperandDisallowed,\n                    // ERC5313 owner\n                    LibParseOperand.handleOperandDisallowed,\n                    // Block number\n                    LibParseOperand.handleOperandDisallowed,\n                    // Chain id\n                    LibParseOperand.handleOperandDisallowed,\n                    // Max int value\n                    LibParseOperand.handleOperandDisallowed,\n                    // Max decimal18 value\n                    LibParseOperand.handleOperandDisallowed,\n                    // Block timestamp\n                    LibParseOperand.handleOperandDisallowed,\n                    // Any\n                    LibParseOperand.handleOperandDisallowed,\n                    // Conditions\n                    LibParseOperand.handleOperandDisallowed,\n                    // Ensure\n                    LibParseOperand.handleOperandDisallowed,\n                    // Equal to\n                    LibParseOperand.handleOperandDisallowed,\n                    // Every\n                    LibParseOperand.handleOperandDisallowed,\n                    // Greater than\n                    LibParseOperand.handleOperandDisallowed,\n                    // Greater than or equal to\n                    LibParseOperand.handleOperandDisallowed,\n                    // If\n                    LibParseOperand.handleOperandDisallowed,\n                    // Is zero\n                    LibParseOperand.handleOperandDisallowed,\n                    // Less than\n                    LibParseOperand.handleOperandDisallowed,\n                    // Less than or equal to\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 exponential growth\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 linear growth\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 avg\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 ceil\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 div\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 exp\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 exp2\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 floor\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 frac\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 gm\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 headroom\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 inv\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 ln\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 log10\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 log2\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 mul\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 power\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 power int\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 scale18 dynamic\n                    LibParseOperand.handleOperandM1M1,\n                    // Decimal18 scale18\n                    LibParseOperand.handleOperand8M1M1,\n                    // Int to decimal18\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 scale n dynamic\n                    LibParseOperand.handleOperandM1M1,\n                    // Decimal18 scale n\n                    LibParseOperand.handleOperand8M1M1,\n                    // Decimal18 to int\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 snap to unit\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 sqrt\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int add\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 add\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int div\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int exp\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int max\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 max\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int min\n                    LibParseOperand.handleOperandDisallowed,\n                    // Decimal18 min\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int mod\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int mul\n                    LibParseOperand.handleOperandDisallowed,\n                    // Int sub\n                    LibParseOperand.handleOperandSingleFull,\n                    // Int saturating sub\n                    LibParseOperand.handleOperandDisallowedAlwaysOne,\n                    // Decimal18 sub\n                    LibParseOperand.handleOperandSingleFull,\n                    // Decimal18 saturating sub\n                    LibParseOperand.handleOperandDisallowedAlwaysOne,\n                    // Get\n                    LibParseOperand.handleOperandDisallowed,\n                    // Set\n                    LibParseOperand.handleOperandDisallowed\n                ];\n            uint256[] memory pointersDynamic;\n            assembly (\"memory-safe\") {\n                pointersDynamic := pointersFixed\n            }\n            // Sanity check that the dynamic length is correct. Should be an\n            // unreachable error.\n            if (pointersDynamic.length != ALL_STANDARD_OPS_LENGTH) {\n                revert BadDynamicLength(pointersDynamic.length, length);\n            }\n            return LibConvert.unsafeTo16BitBytes(pointersDynamic);\n        }\n    }\n\n    function integrityFunctionPointers() internal pure returns (bytes memory) {\n        unchecked {\n            function(IntegrityCheckStateNP memory, Operand)\n                view\n                returns (uint256, uint256) lengthPointer;\n            uint256 length = ALL_STANDARD_OPS_LENGTH;\n            assembly (\"memory-safe\") {\n                lengthPointer := length\n            }\n            function(IntegrityCheckStateNP memory, Operand)\n                view\n                returns (uint256, uint256)[ALL_STANDARD_OPS_LENGTH + 1] memory pointersFixed = [\n                    lengthPointer,\n                    // The first ops are out of lexical ordering so that they\n                    // can sit at stable well known indexes.\n                    LibOpStackNP.integrity,\n                    LibOpConstantNP.integrity,\n                    LibOpExternNP.integrity,\n                    LibOpContextNP.integrity,\n                    // Everything else is alphabetical, including folders.\n                    LibOpBitwiseAndNP.integrity,\n                    LibOpBitwiseOrNP.integrity,\n                    LibOpCtPopNP.integrity,\n                    LibOpDecodeBitsNP.integrity,\n                    LibOpEncodeBitsNP.integrity,\n                    LibOpShiftBitsLeftNP.integrity,\n                    LibOpShiftBitsRightNP.integrity,\n                    LibOpCallNP.integrity,\n                    LibOpHashNP.integrity,\n                    LibOpERC20AllowanceNP.integrity,\n                    LibOpERC20BalanceOfNP.integrity,\n                    LibOpERC20TotalSupplyNP.integrity,\n                    LibOpERC721BalanceOfNP.integrity,\n                    LibOpERC721OwnerOfNP.integrity,\n                    LibOpERC5313OwnerNP.integrity,\n                    LibOpBlockNumberNP.integrity,\n                    LibOpChainIdNP.integrity,\n                    // int and decimal18 max have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpMaxUint256NP.integrity,\n                    // decimal18 max.\n                    LibOpMaxUint256NP.integrity,\n                    LibOpTimestampNP.integrity,\n                    LibOpAnyNP.integrity,\n                    LibOpConditionsNP.integrity,\n                    LibOpEnsureNP.integrity,\n                    LibOpEqualToNP.integrity,\n                    LibOpEveryNP.integrity,\n                    LibOpGreaterThanNP.integrity,\n                    LibOpGreaterThanOrEqualToNP.integrity,\n                    LibOpIfNP.integrity,\n                    LibOpIsZeroNP.integrity,\n                    LibOpLessThanNP.integrity,\n                    LibOpLessThanOrEqualToNP.integrity,\n                    LibOpDecimal18ExponentialGrowthNP.integrity,\n                    LibOpDecimal18LinearGrowthNP.integrity,\n                    LibOpDecimal18AvgNP.integrity,\n                    LibOpDecimal18CeilNP.integrity,\n                    LibOpDecimal18DivNP.integrity,\n                    LibOpDecimal18ExpNP.integrity,\n                    LibOpDecimal18Exp2NP.integrity,\n                    LibOpDecimal18FloorNP.integrity,\n                    LibOpDecimal18FracNP.integrity,\n                    LibOpDecimal18GmNP.integrity,\n                    LibOpDecimal18HeadroomNP.integrity,\n                    LibOpDecimal18InvNP.integrity,\n                    LibOpDecimal18LnNP.integrity,\n                    LibOpDecimal18Log10NP.integrity,\n                    LibOpDecimal18Log2NP.integrity,\n                    LibOpDecimal18MulNP.integrity,\n                    LibOpDecimal18PowNP.integrity,\n                    LibOpDecimal18PowUNP.integrity,\n                    LibOpDecimal18Scale18DynamicNP.integrity,\n                    LibOpDecimal18Scale18NP.integrity,\n                    // Int to decimal18 is a repeat of decimal18 scale18.\n                    LibOpDecimal18Scale18NP.integrity,\n                    LibOpDecimal18ScaleNDynamicNP.integrity,\n                    LibOpDecimal18ScaleNNP.integrity,\n                    // Decimal18 to int is a repeat of decimal18 scaleN.\n                    LibOpDecimal18ScaleNNP.integrity,\n                    LibOpDecimal18SnapToUnitNP.integrity,\n                    LibOpDecimal18SqrtNP.integrity,\n                    // int and decimal18 add have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntAddNP.integrity,\n                    // decimal18 add.\n                    LibOpIntAddNP.integrity,\n                    LibOpIntDivNP.integrity,\n                    LibOpIntExpNP.integrity,\n                    // int and decimal18 max have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntMaxNP.integrity,\n                    // decimal18 max.\n                    LibOpIntMaxNP.integrity,\n                    // int and decimal18 min have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntMinNP.integrity,\n                    // decimal18 min.\n                    LibOpIntMinNP.integrity,\n                    LibOpIntModNP.integrity,\n                    LibOpIntMulNP.integrity,\n                    // int and decimal18 sub have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntSubNP.integrity,\n                    // int saturating sub.\n                    LibOpIntSubNP.integrity,\n                    // decimal18 sub.\n                    LibOpIntSubNP.integrity,\n                    // decimal18 saturating sub.\n                    LibOpIntSubNP.integrity,\n                    LibOpGetNP.integrity,\n                    LibOpSetNP.integrity\n                ];\n            uint256[] memory pointersDynamic;\n            assembly (\"memory-safe\") {\n                pointersDynamic := pointersFixed\n            }\n            // Sanity check that the dynamic length is correct. Should be an\n            // unreachable error.\n            if (pointersDynamic.length != ALL_STANDARD_OPS_LENGTH) {\n                revert BadDynamicLength(pointersDynamic.length, length);\n            }\n            return LibConvert.unsafeTo16BitBytes(pointersDynamic);\n        }\n    }\n\n    /// All function pointers for the standard opcodes. Intended to be used to\n    /// build a `IInterpreterV2` instance, specifically the `functionPointers`\n    /// method can just be a thin wrapper around this function.\n    function opcodeFunctionPointers() internal pure returns (bytes memory) {\n        unchecked {\n            function(InterpreterStateNP memory, Operand, Pointer)\n                view\n                returns (Pointer) lengthPointer;\n            uint256 length = ALL_STANDARD_OPS_LENGTH;\n            assembly (\"memory-safe\") {\n                lengthPointer := length\n            }\n            function(InterpreterStateNP memory, Operand, Pointer)\n                view\n                returns (Pointer)[ALL_STANDARD_OPS_LENGTH + 1] memory pointersFixed = [\n                    lengthPointer,\n                    // The first ops are out of lexical ordering so that they\n                    // can sit at stable well known indexes.\n                    LibOpStackNP.run,\n                    LibOpConstantNP.run,\n                    LibOpExternNP.run,\n                    LibOpContextNP.run,\n                    // Everything else is alphabetical, including folders.\n                    LibOpBitwiseAndNP.run,\n                    LibOpBitwiseOrNP.run,\n                    LibOpCtPopNP.run,\n                    LibOpDecodeBitsNP.run,\n                    LibOpEncodeBitsNP.run,\n                    LibOpShiftBitsLeftNP.run,\n                    LibOpShiftBitsRightNP.run,\n                    LibOpCallNP.run,\n                    LibOpHashNP.run,\n                    LibOpERC20AllowanceNP.run,\n                    LibOpERC20BalanceOfNP.run,\n                    LibOpERC20TotalSupplyNP.run,\n                    LibOpERC721BalanceOfNP.run,\n                    LibOpERC721OwnerOfNP.run,\n                    LibOpERC5313OwnerNP.run,\n                    LibOpBlockNumberNP.run,\n                    LibOpChainIdNP.run,\n                    // int and decimal18 max have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpMaxUint256NP.run,\n                    // decimal18 max.\n                    LibOpMaxUint256NP.run,\n                    LibOpTimestampNP.run,\n                    LibOpAnyNP.run,\n                    LibOpConditionsNP.run,\n                    LibOpEnsureNP.run,\n                    LibOpEqualToNP.run,\n                    LibOpEveryNP.run,\n                    LibOpGreaterThanNP.run,\n                    LibOpGreaterThanOrEqualToNP.run,\n                    LibOpIfNP.run,\n                    LibOpIsZeroNP.run,\n                    LibOpLessThanNP.run,\n                    LibOpLessThanOrEqualToNP.run,\n                    LibOpDecimal18ExponentialGrowthNP.run,\n                    LibOpDecimal18LinearGrowthNP.run,\n                    LibOpDecimal18AvgNP.run,\n                    LibOpDecimal18CeilNP.run,\n                    LibOpDecimal18DivNP.run,\n                    LibOpDecimal18ExpNP.run,\n                    LibOpDecimal18Exp2NP.run,\n                    LibOpDecimal18FloorNP.run,\n                    LibOpDecimal18FracNP.run,\n                    LibOpDecimal18GmNP.run,\n                    LibOpDecimal18HeadroomNP.run,\n                    LibOpDecimal18InvNP.run,\n                    LibOpDecimal18LnNP.run,\n                    LibOpDecimal18Log10NP.run,\n                    LibOpDecimal18Log2NP.run,\n                    LibOpDecimal18MulNP.run,\n                    LibOpDecimal18PowNP.run,\n                    LibOpDecimal18PowUNP.run,\n                    LibOpDecimal18Scale18DynamicNP.run,\n                    LibOpDecimal18Scale18NP.run,\n                    // Int to decimal18 is a repeat of decimal18 scale18.\n                    LibOpDecimal18Scale18NP.run,\n                    LibOpDecimal18ScaleNDynamicNP.run,\n                    LibOpDecimal18ScaleNNP.run,\n                    // Decimal18 to int is a repeat of decimal18 scaleN.\n                    LibOpDecimal18ScaleNNP.run,\n                    LibOpDecimal18SnapToUnitNP.run,\n                    LibOpDecimal18SqrtNP.run,\n                    // int and decimal18 add have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntAddNP.run,\n                    // decimal18 add.\n                    LibOpIntAddNP.run,\n                    LibOpIntDivNP.run,\n                    LibOpIntExpNP.run,\n                    // int and decimal18 max have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntMaxNP.run,\n                    // decimal18 max.\n                    LibOpIntMaxNP.run,\n                    // int and decimal18 min have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntMinNP.run,\n                    // decimal18 min.\n                    LibOpIntMinNP.run,\n                    LibOpIntModNP.run,\n                    LibOpIntMulNP.run,\n                    // int and decimal18 sub have identical implementations and\n                    // point to the same function pointer. This is intentional.\n                    LibOpIntSubNP.run,\n                    // int saturating sub.\n                    LibOpIntSubNP.run,\n                    // decimal18 sub.\n                    LibOpIntSubNP.run,\n                    // decimal18 saturating sub.\n                    LibOpIntSubNP.run,\n                    LibOpGetNP.run,\n                    LibOpSetNP.run\n                ];\n            uint256[] memory pointersDynamic;\n            assembly (\"memory-safe\") {\n                pointersDynamic := pointersFixed\n            }\n            // Sanity check that the dynamic length is correct. Should be an\n            // unreachable error.\n            if (pointersDynamic.length != ALL_STANDARD_OPS_LENGTH) {\n                revert BadDynamicLength(pointersDynamic.length, length);\n            }\n            return LibConvert.unsafeTo16BitBytes(pointersDynamic);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "lib/rain.solmem/src/lib/LibPointer.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// A pointer to a location in memory. This is a `uint256` to save gas on low\n/// level operations on the evm stack. These same low level operations typically\n/// WILL NOT check for overflow or underflow, so all pointer logic MUST ensure\n/// that reads, writes and movements are not out of bounds.\ntype Pointer is uint256;\n\n/// @title LibPointer\n/// Ergonomic wrappers around common pointer movements, reading and writing. As\n/// wrappers on such low level operations often introduce too much jump gas\n/// overhead, these functions MAY find themselves used in reference\n/// implementations that more optimised code can be fuzzed against. MAY also be\n/// situationally useful on cooler performance paths.\nlibrary LibPointer {\n    /// Cast a `Pointer` to `bytes` without modification or any safety checks.\n    /// The caller MUST ensure the pointer is to a valid region of memory for\n    /// some `bytes`.\n    /// @param pointer The pointer to cast to `bytes`.\n    /// @return data The cast `bytes`.\n    function unsafeAsBytes(Pointer pointer) internal pure returns (bytes memory data) {\n        assembly (\"memory-safe\") {\n            data := pointer\n        }\n    }\n\n    /// Increase some pointer by a number of bytes.\n    ///\n    /// This is UNSAFE because it can silently overflow or point beyond some\n    /// data structure. The caller MUST ensure that this is a safe operation.\n    ///\n    /// Note that moving a pointer by some bytes offset is likely to unalign it\n    /// with the 32 byte increments of the Solidity allocator.\n    ///\n    /// @param pointer The pointer to increase by `length`.\n    /// @param length The number of bytes to increase the pointer by.\n    /// @return The increased pointer.\n    function unsafeAddBytes(Pointer pointer, uint256 length) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(pointer, length)\n        }\n        return pointer;\n    }\n\n    /// Increase some pointer by a single 32 byte word.\n    ///\n    /// This is UNSAFE because it can silently overflow or point beyond some\n    /// data structure. The caller MUST ensure that this is a safe operation.\n    ///\n    /// If the original pointer is aligned to the Solidity allocator it will be\n    /// aligned after the movement.\n    ///\n    /// @param pointer The pointer to increase by a single word.\n    /// @return The increased pointer.\n    function unsafeAddWord(Pointer pointer) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(pointer, 0x20)\n        }\n        return pointer;\n    }\n\n    /// Increase some pointer by multiple 32 byte words.\n    ///\n    /// This is UNSAFE because it can silently overflow or point beyond some\n    /// data structure. The caller MUST ensure that this is a safe operation.\n    ///\n    /// If the original pointer is aligned to the Solidity allocator it will be\n    /// aligned after the movement.\n    ///\n    /// @param pointer The pointer to increase.\n    /// @param words The number of words to increase the pointer by.\n    /// @return The increased pointer.\n    function unsafeAddWords(Pointer pointer, uint256 words) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(pointer, mul(0x20, words))\n        }\n        return pointer;\n    }\n\n    /// Decrease some pointer by a single 32 byte word.\n    ///\n    /// This is UNSAFE because it can silently underflow or point below some\n    /// data structure. The caller MUST ensure that this is a safe operation.\n    ///\n    /// If the original pointer is aligned to the Solidity allocator it will be\n    /// aligned after the movement.\n    ///\n    /// @param pointer The pointer to decrease by a single word.\n    /// @return The decreased pointer.\n    function unsafeSubWord(Pointer pointer) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            pointer := sub(pointer, 0x20)\n        }\n        return pointer;\n    }\n\n    /// Decrease some pointer by multiple 32 byte words.\n    ///\n    /// This is UNSAFE because it can silently underflow or point below some\n    /// data structure. The caller MUST ensure that this is a safe operation.\n    ///\n    /// If the original pointer is aligned to the Solidity allocator it will be\n    /// aligned after the movement.\n    ///\n    /// @param pointer The pointer to decrease.\n    /// @param words The number of words to decrease the pointer by.\n    /// @return The decreased pointer.\n    function unsafeSubWords(Pointer pointer, uint256 words) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            pointer := sub(pointer, mul(0x20, words))\n        }\n        return pointer;\n    }\n\n    /// Read the word at the pointer.\n    ///\n    /// This is UNSAFE because it can read outside any particular data stucture\n    /// or even beyond allocated memory. The caller MUST ensure that this is a\n    /// safe operation.\n    ///\n    /// @param pointer Pointer to read the word at.\n    /// @return word The word read from the pointer.\n    function unsafeReadWord(Pointer pointer) internal pure returns (uint256 word) {\n        assembly (\"memory-safe\") {\n            word := mload(pointer)\n        }\n    }\n\n    /// Write a word at the pointer.\n    ///\n    /// This is UNSAFE because it can write outside any particular data stucture\n    /// or even beyond allocated memory. The caller MUST ensure that this is a\n    /// safe operation.\n    ///\n    /// @param pointer Pointer to write the word at.\n    /// @param word The word to write.\n    function unsafeWriteWord(Pointer pointer, uint256 word) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(pointer, word)\n        }\n    }\n\n    /// Get the pointer to the end of all allocated memory.\n    /// As per Solidity docs, there is no guarantee that the region of memory\n    /// beyond this pointer is zeroed out, as assembly MAY write beyond allocated\n    /// memory for temporary use if the scratch space is insufficient.\n    /// @return pointer The pointer to the end of all allocated memory.\n    function allocatedMemoryPointer() internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := mload(0x40)\n        }\n    }\n}\n"
      },
      "lib/rain.solmem/src/lib/LibMemCpy.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport \"./LibPointer.sol\";\n\nlibrary LibMemCpy {\n    /// Copy an arbitrary number of bytes from one location in memory to another.\n    /// As we can only read/write bytes in 32 byte chunks we first have to loop\n    /// over 32 byte values to copy then handle any unaligned remaining data. The\n    /// remaining data will be appropriately masked with the existing data in the\n    /// final chunk so as to not write past the desired length. Note that the\n    /// final unaligned write will be more gas intensive than the prior aligned\n    /// writes. The writes are completely unsafe, the caller MUST ensure that\n    /// sufficient memory is allocated and reading/writing the requested number\n    /// of bytes from/to the requested locations WILL NOT corrupt memory in the\n    /// opinion of solidity or other subsequent read/write operations.\n    /// @param sourceCursor The starting pointer to read from.\n    /// @param targetCursor The starting pointer to write to.\n    /// @param length The number of bytes to read/write.\n    function unsafeCopyBytesTo(Pointer sourceCursor, Pointer targetCursor, uint256 length) internal pure {\n        assembly (\"memory-safe\") {\n            // Precalculating the end here, rather than tracking the remaining\n            // length each iteration uses relatively more gas for less data, but\n            // scales better for more data. Copying 1-2 words is ~30 gas more\n            // expensive but copying 3+ words favours a precalculated end point\n            // increasingly for more data.\n            let m := mod(length, 0x20)\n            let end := add(sourceCursor, sub(length, m))\n            for {} lt(sourceCursor, end) {\n                sourceCursor := add(sourceCursor, 0x20)\n                targetCursor := add(targetCursor, 0x20)\n            } { mstore(targetCursor, mload(sourceCursor)) }\n\n            if iszero(iszero(m)) {\n                //slither-disable-next-line incorrect-shift\n                let mask_ := shr(mul(m, 8), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n                // preserve existing bytes\n                mstore(\n                    targetCursor,\n                    or(\n                        // input\n                        and(mload(sourceCursor), not(mask_)),\n                        and(mload(targetCursor), mask_)\n                    )\n                )\n            }\n        }\n    }\n\n    /// Copies `length` `uint256` values starting from `source` to `target`\n    /// with NO attempt to check that this is safe to do so. The caller MUST\n    /// ensure that there exists allocated memory at `target` in which it is\n    /// safe and appropriate to copy `length * 32` bytes to. Anything that was\n    /// already written to memory at `[target:target+(length * 32 bytes)]`\n    /// will be overwritten.\n    /// There is no return value as memory is modified directly.\n    /// @param source The starting position in memory that data will be copied\n    /// from.\n    /// @param target The starting position in memory that data will be copied\n    /// to.\n    /// @param length The number of 32 byte (i.e. `uint256`) words that will\n    /// be copied.\n    function unsafeCopyWordsTo(Pointer source, Pointer target, uint256 length) internal pure {\n        assembly (\"memory-safe\") {\n            for { let end_ := add(source, mul(0x20, length)) } lt(source, end_) {\n                source := add(source, 0x20)\n                target := add(target, 0x20)\n            } { mstore(target, mload(source)) }\n        }\n    }\n}\n"
      },
      "src/lib/parse/LibParseCMask.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572\ncontract LibParseCMask {}\n\n/// @dev ASCII null\nuint128 constant CMASK_NULL = uint128(1) << uint128(uint8(bytes1(\"\\x00\")));\n\n/// @dev ASCII start of heading\nuint128 constant CMASK_START_OF_HEADING = uint128(1) << uint128(uint8(bytes1(\"\\x01\")));\n\n/// @dev ASCII start of text\nuint128 constant CMASK_START_OF_TEXT = uint128(1) << uint128(uint8(bytes1(\"\\x02\")));\n\n/// @dev ASCII end of text\nuint128 constant CMASK_END_OF_TEXT = uint128(1) << uint128(uint8(bytes1(\"\\x03\")));\n\n/// @dev ASCII end of transmission\nuint128 constant CMASK_END_OF_TRANSMISSION = uint128(1) << uint128(uint8(bytes1(\"\\x04\")));\n\n/// @dev ASCII enquiry\nuint128 constant CMASK_ENQUIRY = uint128(1) << uint128(uint8(bytes1(\"\\x05\")));\n\n/// @dev ASCII acknowledge\nuint128 constant CMASK_ACKNOWLEDGE = uint128(1) << uint128(uint8(bytes1(\"\\x06\")));\n\n/// @dev ASCII bell\nuint128 constant CMASK_BELL = uint128(1) << uint128(uint8(bytes1(\"\\x07\")));\n\n/// @dev ASCII backspace\nuint128 constant CMASK_BACKSPACE = uint128(1) << uint128(uint8(bytes1(\"\\x08\")));\n\n/// @dev ASCII horizontal tab\nuint128 constant CMASK_HORIZONTAL_TAB = uint128(1) << uint128(uint8(bytes1(\"\\t\")));\n\n/// @dev ASCII line feed\nuint128 constant CMASK_LINE_FEED = uint128(1) << uint128(uint8(bytes1(\"\\n\")));\n\n/// @dev ASCII vertical tab\nuint128 constant CMASK_VERTICAL_TAB = uint128(1) << uint128(uint8(bytes1(\"\\x0B\")));\n\n/// @dev ASCII form feed\nuint128 constant CMASK_FORM_FEED = uint128(1) << uint128(uint8(bytes1(\"\\x0C\")));\n\n/// @dev ASCII carriage return\nuint128 constant CMASK_CARRIAGE_RETURN = uint128(1) << uint128(uint8(bytes1(\"\\r\")));\n\n/// @dev ASCII shift out\nuint128 constant CMASK_SHIFT_OUT = uint128(1) << uint128(uint8(bytes1(\"\\x0E\")));\n\n/// @dev ASCII shift in\nuint128 constant CMASK_SHIFT_IN = uint128(1) << uint128(uint8(bytes1(\"\\x0F\")));\n\n/// @dev ASCII data link escape\nuint128 constant CMASK_DATA_LINK_ESCAPE = uint128(1) << uint128(uint8(bytes1(\"\\x10\")));\n\n/// @dev ASCII device control 1\nuint128 constant CMASK_DEVICE_CONTROL_1 = uint128(1) << uint128(uint8(bytes1(\"\\x11\")));\n\n/// @dev ASCII device control 2\nuint128 constant CMASK_DEVICE_CONTROL_2 = uint128(1) << uint128(uint8(bytes1(\"\\x12\")));\n\n/// @dev ASCII device control 3\nuint128 constant CMASK_DEVICE_CONTROL_3 = uint128(1) << uint128(uint8(bytes1(\"\\x13\")));\n\n/// @dev ASCII device control 4\nuint128 constant CMASK_DEVICE_CONTROL_4 = uint128(1) << uint128(uint8(bytes1(\"\\x14\")));\n\n/// @dev ASCII negative acknowledge\nuint128 constant CMASK_NEGATIVE_ACKNOWLEDGE = uint128(1) << uint128(uint8(bytes1(\"\\x15\")));\n\n/// @dev ASCII synchronous idle\nuint128 constant CMASK_SYNCHRONOUS_IDLE = uint128(1) << uint128(uint8(bytes1(\"\\x16\")));\n\n/// @dev ASCII end of transmission block\nuint128 constant CMASK_END_OF_TRANSMISSION_BLOCK = uint128(1) << uint128(uint8(bytes1(\"\\x17\")));\n\n/// @dev ASCII cancel\nuint128 constant CMASK_CANCEL = uint128(1) << uint128(uint8(bytes1(\"\\x18\")));\n\n/// @dev ASCII end of medium\nuint128 constant CMASK_END_OF_MEDIUM = uint128(1) << uint128(uint8(bytes1(\"\\x19\")));\n\n/// @dev ASCII substitute\nuint128 constant CMASK_SUBSTITUTE = uint128(1) << uint128(uint8(bytes1(\"\\x1A\")));\n\n/// @dev ASCII escape\nuint128 constant CMASK_ESCAPE = uint128(1) << uint128(uint8(bytes1(\"\\x1B\")));\n\n/// @dev ASCII file separator\nuint128 constant CMASK_FILE_SEPARATOR = uint128(1) << uint128(uint8(bytes1(\"\\x1C\")));\n\n/// @dev ASCII group separator\nuint128 constant CMASK_GROUP_SEPARATOR = uint128(1) << uint128(uint8(bytes1(\"\\x1D\")));\n\n/// @dev ASCII record separator\nuint128 constant CMASK_RECORD_SEPARATOR = uint128(1) << uint128(uint8(bytes1(\"\\x1E\")));\n\n/// @dev ASCII unit separator\nuint128 constant CMASK_UNIT_SEPARATOR = uint128(1) << uint128(uint8(bytes1(\"\\x1F\")));\n\n/// @dev ASCII space\nuint128 constant CMASK_SPACE = uint128(1) << uint128(uint8(bytes1(\" \")));\n\n/// @dev ASCII !\nuint128 constant CMASK_EXCLAMATION_MARK = uint128(1) << uint128(uint8(bytes1(\"!\")));\n\n/// @dev ASCII \"\nuint128 constant CMASK_QUOTATION_MARK = uint128(1) << uint128(uint8(bytes1(\"\\\"\")));\n\n/// @dev ASCII #\nuint128 constant CMASK_NUMBER_SIGN = uint128(1) << uint128(uint8(bytes1(\"#\")));\n\n/// @dev ASCII $\nuint128 constant CMASK_DOLLAR_SIGN = uint128(1) << uint128(uint8(bytes1(\"$\")));\n\n/// @dev ASCII %\nuint128 constant CMASK_PERCENT_SIGN = uint128(1) << uint128(uint8(bytes1(\"%\")));\n\n/// @dev ASCII &\nuint128 constant CMASK_AMPERSAND = uint128(1) << uint128(uint8(bytes1(\"&\")));\n\n/// @dev ASCII '\nuint128 constant CMASK_APOSTROPHE = uint128(1) << uint128(uint8(bytes1(\"'\")));\n\n/// @dev ASCII (\nuint128 constant CMASK_LEFT_PAREN = uint128(1) << uint128(uint8(bytes1(\"(\")));\n\n/// @dev ASCII )\nuint128 constant CMASK_RIGHT_PAREN = uint128(1) << uint128(uint8(bytes1(\")\")));\n\n/// @dev ASCII *\nuint128 constant CMASK_ASTERISK = uint128(1) << uint128(uint8(bytes1(\"*\")));\n\n/// @dev ASCII +\nuint128 constant CMASK_PLUS_SIGN = uint128(1) << uint128(uint8(bytes1(\"+\")));\n\n/// @dev ASCII ,\nuint128 constant CMASK_COMMA = uint128(1) << uint128(uint8(bytes1(\",\")));\n\n/// @dev ASCII -\nuint128 constant CMASK_DASH = uint128(1) << uint128(uint8(bytes1(\"-\")));\n\n/// @dev ASCII .\nuint128 constant CMASK_FULL_STOP = uint128(1) << uint128(uint8(bytes1(\".\")));\n\n/// @dev ASCII /\nuint128 constant CMASK_SLASH = uint128(1) << uint128(uint8(bytes1(\"/\")));\n\n/// @dev ASCII 0\nuint128 constant CMASK_ZERO = uint128(1) << uint128(uint8(bytes1(\"0\")));\n\n/// @dev ASCII 1\nuint128 constant CMASK_ONE = uint128(1) << uint128(uint8(bytes1(\"1\")));\n\n/// @dev ASCII 2\nuint128 constant CMASK_TWO = uint128(1) << uint128(uint8(bytes1(\"2\")));\n\n/// @dev ASCII 3\nuint128 constant CMASK_THREE = uint128(1) << uint128(uint8(bytes1(\"3\")));\n\n/// @dev ASCII 4\nuint128 constant CMASK_FOUR = uint128(1) << uint128(uint8(bytes1(\"4\")));\n\n/// @dev ASCII 5\nuint128 constant CMASK_FIVE = uint128(1) << uint128(uint8(bytes1(\"5\")));\n\n/// @dev ASCII 6\nuint128 constant CMASK_SIX = uint128(1) << uint128(uint8(bytes1(\"6\")));\n\n/// @dev ASCII 7\nuint128 constant CMASK_SEVEN = uint128(1) << uint128(uint8(bytes1(\"7\")));\n\n/// @dev ASCII 8\nuint128 constant CMASK_EIGHT = uint128(1) << uint128(uint8(bytes1(\"8\")));\n\n/// @dev ASCII 9\nuint128 constant CMASK_NINE = uint128(1) << uint128(uint8(bytes1(\"9\")));\n\n/// @dev ASCII :\nuint128 constant CMASK_COLON = uint128(1) << uint128(uint8(bytes1(\":\")));\n\n/// @dev ASCII ;\nuint128 constant CMASK_SEMICOLON = uint128(1) << uint128(uint8(bytes1(\";\")));\n\n/// @dev ASCII <\nuint128 constant CMASK_LESS_THAN_SIGN = uint128(1) << uint128(uint8(bytes1(\"<\")));\n\n/// @dev ASCII =\nuint128 constant CMASK_EQUALS_SIGN = uint128(1) << uint128(uint8(bytes1(\"=\")));\n\n/// @dev ASCII >\nuint128 constant CMASK_GREATER_THAN_SIGN = uint128(1) << uint128(uint8(bytes1(\">\")));\n\n/// @dev ASCII ?\nuint128 constant CMASK_QUESTION_MARK = uint128(1) << uint128(uint8(bytes1(\"?\")));\n\n/// @dev ASCII @\nuint128 constant CMASK_AT_SIGN = uint128(1) << uint128(uint8(bytes1(\"@\")));\n\n/// @dev ASCII A\nuint128 constant CMASK_UPPER_A = uint128(1) << uint128(uint8(bytes1(\"A\")));\n\n/// @dev ASCII B\nuint128 constant CMASK_UPPER_B = uint128(1) << uint128(uint8(bytes1(\"B\")));\n\n/// @dev ASCII C\nuint128 constant CMASK_UPPER_C = uint128(1) << uint128(uint8(bytes1(\"C\")));\n\n/// @dev ASCII D\nuint128 constant CMASK_UPPER_D = uint128(1) << uint128(uint8(bytes1(\"D\")));\n\n/// @dev ASCII E\nuint128 constant CMASK_UPPER_E = uint128(1) << uint128(uint8(bytes1(\"E\")));\n\n/// @dev ASCII F\nuint128 constant CMASK_UPPER_F = uint128(1) << uint128(uint8(bytes1(\"F\")));\n\n/// @dev ASCII G\nuint128 constant CMASK_UPPER_G = uint128(1) << uint128(uint8(bytes1(\"G\")));\n\n/// @dev ASCII H\nuint128 constant CMASK_UPPER_H = uint128(1) << uint128(uint8(bytes1(\"H\")));\n\n/// @dev ASCII I\nuint128 constant CMASK_UPPER_I = uint128(1) << uint128(uint8(bytes1(\"I\")));\n\n/// @dev ASCII J\nuint128 constant CMASK_UPPER_J = uint128(1) << uint128(uint8(bytes1(\"J\")));\n\n/// @dev ASCII K\nuint128 constant CMASK_UPPER_K = uint128(1) << uint128(uint8(bytes1(\"K\")));\n\n/// @dev ASCII L\nuint128 constant CMASK_UPPER_L = uint128(1) << uint128(uint8(bytes1(\"L\")));\n\n/// @dev ASCII M\nuint128 constant CMASK_UPPER_M = uint128(1) << uint128(uint8(bytes1(\"M\")));\n\n/// @dev ASCII N\nuint128 constant CMASK_UPPER_N = uint128(1) << uint128(uint8(bytes1(\"N\")));\n\n/// @dev ASCII O\nuint128 constant CMASK_UPPER_O = uint128(1) << uint128(uint8(bytes1(\"O\")));\n\n/// @dev ASCII P\nuint128 constant CMASK_UPPER_P = uint128(1) << uint128(uint8(bytes1(\"P\")));\n\n/// @dev ASCII Q\nuint128 constant CMASK_UPPER_Q = uint128(1) << uint128(uint8(bytes1(\"Q\")));\n\n/// @dev ASCII R\nuint128 constant CMASK_UPPER_R = uint128(1) << uint128(uint8(bytes1(\"R\")));\n\n/// @dev ASCII S\nuint128 constant CMASK_UPPER_S = uint128(1) << uint128(uint8(bytes1(\"S\")));\n\n/// @dev ASCII T\nuint128 constant CMASK_UPPER_T = uint128(1) << uint128(uint8(bytes1(\"T\")));\n\n/// @dev ASCII U\nuint128 constant CMASK_UPPER_U = uint128(1) << uint128(uint8(bytes1(\"U\")));\n\n/// @dev ASCII V\nuint128 constant CMASK_UPPER_V = uint128(1) << uint128(uint8(bytes1(\"V\")));\n\n/// @dev ASCII W\nuint128 constant CMASK_UPPER_W = uint128(1) << uint128(uint8(bytes1(\"W\")));\n\n/// @dev ASCII X\nuint128 constant CMASK_UPPER_X = uint128(1) << uint128(uint8(bytes1(\"X\")));\n\n/// @dev ASCII Y\nuint128 constant CMASK_UPPER_Y = uint128(1) << uint128(uint8(bytes1(\"Y\")));\n\n/// @dev ASCII Z\nuint128 constant CMASK_UPPER_Z = uint128(1) << uint128(uint8(bytes1(\"Z\")));\n\n/// @dev ASCII [\nuint128 constant CMASK_LEFT_SQUARE_BRACKET = uint128(1) << uint128(uint8(bytes1(\"[\")));\n\n/// @dev ASCII \\\nuint128 constant CMASK_BACKSLASH = uint128(1) << uint128(uint8(bytes1(\"\\\\\")));\n\n/// @dev ASCII ]\nuint128 constant CMASK_RIGHT_SQUARE_BRACKET = uint128(1) << uint128(uint8(bytes1(\"]\")));\n\n/// @dev ASCII ^\nuint128 constant CMASK_CIRCUMFLEX_ACCENT = uint128(1) << uint128(uint8(bytes1(\"^\")));\n\n/// @dev ASCII _\nuint128 constant CMASK_UNDERSCORE = uint128(1) << uint128(uint8(bytes1(\"_\")));\n\n/// @dev ASCII `\nuint128 constant CMASK_GRAVE_ACCENT = uint128(1) << uint128(uint8(bytes1(\"`\")));\n\n/// @dev ASCII a\nuint128 constant CMASK_LOWER_A = uint128(1) << uint128(uint8(bytes1(\"a\")));\n\n/// @dev ASCII b\nuint128 constant CMASK_LOWER_B = uint128(1) << uint128(uint8(bytes1(\"b\")));\n\n/// @dev ASCII c\nuint128 constant CMASK_LOWER_C = uint128(1) << uint128(uint8(bytes1(\"c\")));\n\n/// @dev ASCII d\nuint128 constant CMASK_LOWER_D = uint128(1) << uint128(uint8(bytes1(\"d\")));\n\n/// @dev ASCII e\nuint128 constant CMASK_LOWER_E = uint128(1) << uint128(uint8(bytes1(\"e\")));\n\n/// @dev ASCII f\nuint128 constant CMASK_LOWER_F = uint128(1) << uint128(uint8(bytes1(\"f\")));\n\n/// @dev ASCII g\nuint128 constant CMASK_LOWER_G = uint128(1) << uint128(uint8(bytes1(\"g\")));\n\n/// @dev ASCII h\nuint128 constant CMASK_LOWER_H = uint128(1) << uint128(uint8(bytes1(\"h\")));\n\n/// @dev ASCII i\nuint128 constant CMASK_LOWER_I = uint128(1) << uint128(uint8(bytes1(\"i\")));\n\n/// @dev ASCII j\nuint128 constant CMASK_LOWER_J = uint128(1) << uint128(uint8(bytes1(\"j\")));\n\n/// @dev ASCII k\nuint128 constant CMASK_LOWER_K = uint128(1) << uint128(uint8(bytes1(\"k\")));\n\n/// @dev ASCII l\nuint128 constant CMASK_LOWER_L = uint128(1) << uint128(uint8(bytes1(\"l\")));\n\n/// @dev ASCII m\nuint128 constant CMASK_LOWER_M = uint128(1) << uint128(uint8(bytes1(\"m\")));\n\n/// @dev ASCII n\nuint128 constant CMASK_LOWER_N = uint128(1) << uint128(uint8(bytes1(\"n\")));\n\n/// @dev ASCII o\nuint128 constant CMASK_LOWER_O = uint128(1) << uint128(uint8(bytes1(\"o\")));\n\n/// @dev ASCII p\nuint128 constant CMASK_LOWER_P = uint128(1) << uint128(uint8(bytes1(\"p\")));\n\n/// @dev ASCII q\nuint128 constant CMASK_LOWER_Q = uint128(1) << uint128(uint8(bytes1(\"q\")));\n\n/// @dev ASCII r\nuint128 constant CMASK_LOWER_R = uint128(1) << uint128(uint8(bytes1(\"r\")));\n\n/// @dev ASCII s\nuint128 constant CMASK_LOWER_S = uint128(1) << uint128(uint8(bytes1(\"s\")));\n\n/// @dev ASCII t\nuint128 constant CMASK_LOWER_T = uint128(1) << uint128(uint8(bytes1(\"t\")));\n\n/// @dev ASCII u\nuint128 constant CMASK_LOWER_U = uint128(1) << uint128(uint8(bytes1(\"u\")));\n\n/// @dev ASCII v\nuint128 constant CMASK_LOWER_V = uint128(1) << uint128(uint8(bytes1(\"v\")));\n\n/// @dev ASCII w\nuint128 constant CMASK_LOWER_W = uint128(1) << uint128(uint8(bytes1(\"w\")));\n\n/// @dev ASCII x\nuint128 constant CMASK_LOWER_X = uint128(1) << uint128(uint8(bytes1(\"x\")));\n\n/// @dev ASCII y\nuint128 constant CMASK_LOWER_Y = uint128(1) << uint128(uint8(bytes1(\"y\")));\n\n/// @dev ASCII z\nuint128 constant CMASK_LOWER_Z = uint128(1) << uint128(uint8(bytes1(\"z\")));\n\n/// @dev ASCII {\nuint128 constant CMASK_LEFT_CURLY_BRACKET = uint128(1) << uint128(uint8(bytes1(\"{\")));\n\n/// @dev ASCII |\nuint128 constant CMASK_VERTICAL_BAR = uint128(1) << uint128(uint8(bytes1(\"|\")));\n\n/// @dev ASCII }\nuint128 constant CMASK_RIGHT_CURLY_BRACKET = uint128(1) << uint128(uint8(bytes1(\"}\")));\n\n/// @dev ASCII ~\nuint128 constant CMASK_TILDE = uint128(1) << uint128(uint8(bytes1(\"~\")));\n\n/// @dev ASCII delete\nuint128 constant CMASK_DELETE = uint128(1) << uint128(uint8(bytes1(\"\\x7F\")));\n\n/// @dev ASCII printable characters is everything 0x20 and above, except 0x7F\nuint128 constant CMASK_PRINTABLE = ~(\n    CMASK_NULL | CMASK_START_OF_HEADING | CMASK_START_OF_TEXT | CMASK_END_OF_TEXT | CMASK_END_OF_TRANSMISSION\n        | CMASK_ENQUIRY | CMASK_ACKNOWLEDGE | CMASK_BELL | CMASK_BACKSPACE | CMASK_HORIZONTAL_TAB | CMASK_LINE_FEED\n        | CMASK_VERTICAL_TAB | CMASK_FORM_FEED | CMASK_CARRIAGE_RETURN | CMASK_SHIFT_OUT | CMASK_SHIFT_IN\n        | CMASK_DATA_LINK_ESCAPE | CMASK_DEVICE_CONTROL_1 | CMASK_DEVICE_CONTROL_2 | CMASK_DEVICE_CONTROL_3\n        | CMASK_DEVICE_CONTROL_4 | CMASK_NEGATIVE_ACKNOWLEDGE | CMASK_SYNCHRONOUS_IDLE | CMASK_END_OF_TRANSMISSION_BLOCK\n        | CMASK_CANCEL | CMASK_END_OF_MEDIUM | CMASK_SUBSTITUTE | CMASK_ESCAPE | CMASK_FILE_SEPARATOR\n        | CMASK_GROUP_SEPARATOR | CMASK_RECORD_SEPARATOR | CMASK_UNIT_SEPARATOR | CMASK_DELETE\n);\n\n/// @dev numeric 0-9\nuint128 constant CMASK_NUMERIC_0_9 = CMASK_ZERO | CMASK_ONE | CMASK_TWO | CMASK_THREE | CMASK_FOUR | CMASK_FIVE\n    | CMASK_SIX | CMASK_SEVEN | CMASK_EIGHT | CMASK_NINE;\n\n/// @dev e notation eE\nuint128 constant CMASK_E_NOTATION = CMASK_LOWER_E | CMASK_UPPER_E;\n\n/// @dev lower alpha a-z\nuint128 constant CMASK_LOWER_ALPHA_A_Z = CMASK_LOWER_A | CMASK_LOWER_B | CMASK_LOWER_C | CMASK_LOWER_D | CMASK_LOWER_E\n    | CMASK_LOWER_F | CMASK_LOWER_G | CMASK_LOWER_H | CMASK_LOWER_I | CMASK_LOWER_J | CMASK_LOWER_K | CMASK_LOWER_L\n    | CMASK_LOWER_M | CMASK_LOWER_N | CMASK_LOWER_O | CMASK_LOWER_P | CMASK_LOWER_Q | CMASK_LOWER_R | CMASK_LOWER_S\n    | CMASK_LOWER_T | CMASK_LOWER_U | CMASK_LOWER_V | CMASK_LOWER_W | CMASK_LOWER_X | CMASK_LOWER_Y | CMASK_LOWER_Z;\n\n/// @dev upper alpha A-Z\nuint128 constant CMASK_UPPER_ALPHA_A_Z = CMASK_UPPER_A | CMASK_UPPER_B | CMASK_UPPER_C | CMASK_UPPER_D | CMASK_UPPER_E\n    | CMASK_UPPER_F | CMASK_UPPER_G | CMASK_UPPER_H | CMASK_UPPER_I | CMASK_UPPER_J | CMASK_UPPER_K | CMASK_UPPER_L\n    | CMASK_UPPER_M | CMASK_UPPER_N | CMASK_UPPER_O | CMASK_UPPER_P | CMASK_UPPER_Q | CMASK_UPPER_R | CMASK_UPPER_S\n    | CMASK_UPPER_T | CMASK_UPPER_U | CMASK_UPPER_V | CMASK_UPPER_W | CMASK_UPPER_X | CMASK_UPPER_Y | CMASK_UPPER_Z;\n\n/// @dev lower alpha a-f (hex)\nuint128 constant CMASK_LOWER_ALPHA_A_F =\n    CMASK_LOWER_A | CMASK_LOWER_B | CMASK_LOWER_C | CMASK_LOWER_D | CMASK_LOWER_E | CMASK_LOWER_F;\n\n/// @dev upper alpha A-F (hex)\nuint128 constant CMASK_UPPER_ALPHA_A_F =\n    CMASK_UPPER_A | CMASK_UPPER_B | CMASK_UPPER_C | CMASK_UPPER_D | CMASK_UPPER_E | CMASK_UPPER_F;\n\n/// @dev hex 0-9 a-f A-F\nuint128 constant CMASK_HEX = CMASK_NUMERIC_0_9 | CMASK_LOWER_ALPHA_A_F | CMASK_UPPER_ALPHA_A_F;\n\n/// @dev Rainlang end of line is ,\nuint128 constant CMASK_EOL = CMASK_COMMA;\n\n/// @dev Rainlang LHS/RHS delimiter is :\nuint128 constant CMASK_LHS_RHS_DELIMITER = CMASK_COLON;\n\n/// @dev Rainlang end of source is ;\nuint128 constant CMASK_EOS = CMASK_SEMICOLON;\n\n/// @dev Rainlang stack head is lower alpha and underscore a-z _\nuint128 constant CMASK_LHS_STACK_HEAD = CMASK_LOWER_ALPHA_A_Z | CMASK_UNDERSCORE;\n\n/// @dev Rainlang identifier head is lower alpha a-z\nuint128 constant CMASK_IDENTIFIER_HEAD = CMASK_LOWER_ALPHA_A_Z;\nuint128 constant CMASK_RHS_WORD_HEAD = CMASK_IDENTIFIER_HEAD;\n\n/// @dev Rainlang stack/identifier tail is lower alphanumeric kebab a-z 0-9 -\nuint128 constant CMASK_IDENTIFIER_TAIL = CMASK_IDENTIFIER_HEAD | CMASK_NUMERIC_0_9 | CMASK_DASH;\nuint128 constant CMASK_LHS_STACK_TAIL = CMASK_IDENTIFIER_TAIL;\nuint128 constant CMASK_RHS_WORD_TAIL = CMASK_IDENTIFIER_TAIL;\n\n/// @dev Rainlang operand start is <\nuint128 constant CMASK_OPERAND_START = CMASK_LESS_THAN_SIGN;\n\n/// @dev Rainlang operand end is >\nuint128 constant CMASK_OPERAND_END = CMASK_GREATER_THAN_SIGN;\n\n/// @dev NOT lower alphanumeric kebab\nuint128 constant CMASK_NOT_IDENTIFIER_TAIL = ~CMASK_IDENTIFIER_TAIL;\n\n/// @dev Rainlang whitespace is \\n \\r \\t space\nuint128 constant CMASK_WHITESPACE = CMASK_LINE_FEED | CMASK_CARRIAGE_RETURN | CMASK_HORIZONTAL_TAB | CMASK_SPACE;\n\n/// @dev Rainlang stack item delimiter is whitespace\nuint128 constant CMASK_LHS_STACK_DELIMITER = CMASK_WHITESPACE;\n\n/// @dev Rainlang supports numeric literals as anything starting with 0-9\nuint128 constant CMASK_NUMERIC_LITERAL_HEAD = CMASK_NUMERIC_0_9;\n\n/// @dev Rainlang supports string literals as anything starting with \"\nuint128 constant CMASK_STRING_LITERAL_HEAD = CMASK_QUOTATION_MARK;\n\n/// @dev Rainlang supports sub parseable literals as anything starting with [\nuint128 constant CMASK_SUB_PARSEABLE_LITERAL_HEAD = CMASK_LEFT_SQUARE_BRACKET;\n\n/// @dev Rainlang ends a sub parseable literal with ]\nuint128 constant CMASK_SUB_PARSEABLE_LITERAL_END = CMASK_RIGHT_SQUARE_BRACKET;\n\n/// @dev Rainlang string end is \"\nuint128 constant CMASK_STRING_LITERAL_END = CMASK_QUOTATION_MARK;\n\n/// @dev Rainlang string tail is any printable ASCII except \" which ends it.\nuint128 constant CMASK_STRING_LITERAL_TAIL = ~CMASK_STRING_LITERAL_END & CMASK_PRINTABLE;\n\n/// @dev Rainlang literal head\nuint128 constant CMASK_LITERAL_HEAD =\n    CMASK_NUMERIC_LITERAL_HEAD | CMASK_STRING_LITERAL_HEAD | CMASK_SUB_PARSEABLE_LITERAL_HEAD;\n\n/// @dev Rainlang comment head is /\nuint128 constant CMASK_COMMENT_HEAD = CMASK_SLASH;\n\n/// @dev Rainlang interstitial head could be some whitespace or a comment head.\nuint128 constant CMASK_INTERSTITIAL_HEAD = CMASK_WHITESPACE | CMASK_COMMENT_HEAD;\n\n/// @dev Rainlang comment starting sequence is /*\nuint256 constant COMMENT_START_SEQUENCE = uint256(uint16(bytes2(\"/*\")));\n\n/// @dev Rainlang comment ending sequence is */\nuint256 constant COMMENT_END_SEQUENCE = uint256(uint16(bytes2(\"*/\")));\n\n/// @dev Rainlang comment end sequence end byte is / */\nuint256 constant CMASK_COMMENT_END_SEQUENCE_END = COMMENT_END_SEQUENCE & 0xFF;\n\n/// @dev Rainlang literal hexadecimal dispatch is 0x\n/// We compare the head and dispatch together to avoid a second comparison.\n/// This is safe because the head is prefiltered to be 0-9 due to the numeric\n/// literal head, therefore the only possible match is 0x (not x0).\nuint128 constant CMASK_LITERAL_HEX_DISPATCH = CMASK_ZERO | CMASK_LOWER_X;\n\n/// @dev We may want to match the exact start of a hex literal.\nuint256 constant CMASK_LITERAL_HEX_DISPATCH_START = uint256(uint16(bytes2(\"0x\")));\n"
      },
      "src/lib/bitwise/LibCtPop.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev 010101... for ctpop\nuint256 constant CTPOP_M1 = 0x5555555555555555555555555555555555555555555555555555555555555555;\n/// @dev 00110011.. for ctpop\nuint256 constant CTPOP_M2 = 0x3333333333333333333333333333333333333333333333333333333333333333;\n/// @dev 4 bits alternating for ctpop\nuint256 constant CTPOP_M4 = 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F;\n/// @dev 8 bits alternating for ctpop\nuint256 constant CTPOP_M8 = 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF;\n/// @dev 16 bits alternating for ctpop\nuint256 constant CTPOP_M16 = 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF;\n/// @dev 32 bits alternating for ctpop\nuint256 constant CTPOP_M32 = 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF;\n/// @dev 64 bits alternating for ctpop\nuint256 constant CTPOP_M64 = 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF;\n/// @dev 128 bits alternating for ctpop\nuint256 constant CTPOP_M128 = 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n/// @dev 1 bytes for ctpop\nuint256 constant CTPOP_H01 = 0x0101010101010101010101010101010101010101010101010101010101010101;\n\nlibrary LibCtPop {\n    /// Optimised version of ctpop.\n    /// https://en.wikipedia.org/wiki/Hamming_weight\n    function ctpop(uint256 x) internal pure returns (uint256) {\n        // This edge case is not handled by the algorithm below.\n        if (x == type(uint256).max) {\n            return 256;\n        }\n        unchecked {\n            x -= (x >> 1) & CTPOP_M1;\n            x = (x & CTPOP_M2) + ((x >> 2) & CTPOP_M2);\n            x = (x + (x >> 4)) & CTPOP_M4;\n            x = (x * CTPOP_H01) >> 248;\n        }\n        return x;\n    }\n\n    /// This is the slowest possible implementation of ctpop. It is used to\n    /// verify the correctness of the optimized implementation in LibCtPop.\n    /// It should be obviously correct by visual inspection, referencing the\n    /// wikipedia article.\n    /// https://en.wikipedia.org/wiki/Hamming_weight\n    function ctpopSlow(uint256 x) internal pure returns (uint256) {\n        unchecked {\n            x = (x & CTPOP_M1) + ((x >> 1) & CTPOP_M1);\n            x = (x & CTPOP_M2) + ((x >> 2) & CTPOP_M2);\n            x = (x & CTPOP_M4) + ((x >> 4) & CTPOP_M4);\n            x = (x & CTPOP_M8) + ((x >> 8) & CTPOP_M8);\n            x = (x & CTPOP_M16) + ((x >> 16) & CTPOP_M16);\n            x = (x & CTPOP_M32) + ((x >> 32) & CTPOP_M32);\n            x = (x & CTPOP_M64) + ((x >> 64) & CTPOP_M64);\n            x = (x & CTPOP_M128) + ((x >> 128) & CTPOP_M128);\n        }\n        return x;\n    }\n}\n"
      },
      "src/lib/parse/LibParseMeta.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibCtPop} from \"../bitwise/LibCtPop.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {LibParseOperand} from \"./LibParseOperand.sol\";\nimport {ParseState} from \"./LibParseState.sol\";\nimport {AuthoringMetaV2} from \"rain.interpreter.interface/interface/IParserV1.sol\";\n\n/// @dev For metadata builder.\nerror DuplicateFingerprint();\n\n/// @dev Words and io fn pointers aren't the same length.\nerror WordIOFnPointerMismatch(uint256 wordsLength, uint256 ioFnPointersLength);\n\n/// @dev 0xFFFFFF = 3 byte fingerprint\n/// The fingerprint is 3 bytes because we're targetting the same collision\n/// resistance on words as solidity functions. As we already use a fully byte to\n/// map words across the expander, we only need 3 bytes for the fingerprint to\n/// achieve 4 bytes of collision resistance, which is the same as a solidity\n/// selector. This assumes that the byte selected to expand is uncorrelated with\n/// the fingerprint bytes, which is a reasonable assumption as long as we use\n/// different bytes from a keccak256 hash for each.\n/// This assumes a single expander, if there are multiple expanders, then the\n/// collision resistance only improves, so this is still safe.\nuint256 constant FINGERPRINT_MASK = 0xFFFFFF;\n/// @dev 4 = 1 byte opcode index + 3 byte fingerprint\nuint256 constant META_ITEM_SIZE = 4;\nuint256 constant META_ITEM_MASK = (1 << META_ITEM_SIZE) - 1;\n/// @dev 33 = 32 bytes for expansion + 1 byte for seed\nuint256 constant META_EXPANSION_SIZE = 0x21;\n/// @dev 1 = 1 byte for depth\nuint256 constant META_PREFIX_SIZE = 1;\n\nlibrary LibParseMeta {\n    function wordBitmapped(uint256 seed, bytes32 word) internal pure returns (uint256 bitmap, uint256 hashed) {\n        assembly (\"memory-safe\") {\n            mstore(0, word)\n            mstore8(0x20, seed)\n            hashed := keccak256(0, 0x21)\n            // We have to be careful here to avoid using the same byte for both\n            // the expansion and the fingerprint. This is because we are relying\n            // on the combined effect of both for collision resistance. We do\n            // this by using the high byte of the hash for the bitmap, and the\n            // low 3 bytes for the fingerprint.\n            //slither-disable-next-line incorrect-shift\n            bitmap := shl(byte(0, hashed), 1)\n        }\n    }\n\n    function copyWordsFromAuthoringMeta(AuthoringMetaV2[] memory authoringMeta)\n        internal\n        pure\n        returns (bytes32[] memory)\n    {\n        bytes32[] memory words = new bytes32[](authoringMeta.length);\n        for (uint256 i = 0; i < authoringMeta.length; i++) {\n            words[i] = authoringMeta[i].word;\n        }\n        return words;\n    }\n\n    function findBestExpander(AuthoringMetaV2[] memory metas)\n        internal\n        pure\n        returns (uint8 bestSeed, uint256 bestExpansion, AuthoringMetaV2[] memory remaining)\n    {\n        unchecked {\n            {\n                uint256 bestCt = 0;\n                for (uint256 seed = 0; seed < type(uint8).max; seed++) {\n                    uint256 expansion = 0;\n                    for (uint256 i = 0; i < metas.length; i++) {\n                        (uint256 shifted, uint256 hashed) = wordBitmapped(seed, metas[i].word);\n                        (hashed);\n                        expansion = shifted | expansion;\n                    }\n                    uint256 ct = LibCtPop.ctpop(expansion);\n                    if (ct > bestCt) {\n                        bestCt = ct;\n                        bestSeed = uint8(seed);\n                        bestExpansion = expansion;\n                    }\n                    // perfect expansion.\n                    if (ct == metas.length) {\n                        break;\n                    }\n                }\n\n                uint256 remainingLength = metas.length - bestCt;\n                assembly (\"memory-safe\") {\n                    remaining := mload(0x40)\n                    mstore(remaining, remainingLength)\n                    mstore(0x40, add(remaining, mul(0x20, add(1, remainingLength))))\n                }\n            }\n            uint256 usedExpansion = 0;\n            uint256 j = 0;\n            for (uint256 i = 0; i < metas.length; i++) {\n                (uint256 shifted, uint256 hashed) = wordBitmapped(bestSeed, metas[i].word);\n                (hashed);\n                if ((shifted & usedExpansion) == 0) {\n                    usedExpansion = shifted | usedExpansion;\n                } else {\n                    remaining[j] = metas[i];\n                    j++;\n                }\n            }\n        }\n    }\n\n    function buildParseMetaV2(AuthoringMetaV2[] memory authoringMeta, uint8 maxDepth)\n        internal\n        pure\n        returns (bytes memory parseMeta)\n    {\n        unchecked {\n            // Write out expansions.\n            uint8[] memory seeds;\n            uint256[] memory expansions;\n            uint256 dataStart;\n            {\n                uint256 depth = 0;\n                seeds = new uint8[](maxDepth);\n                expansions = new uint256[](maxDepth);\n                {\n                    AuthoringMetaV2[] memory remainingAuthoringMeta = authoringMeta;\n                    while (remainingAuthoringMeta.length > 0) {\n                        uint8 seed;\n                        uint256 expansion;\n                        (seed, expansion, remainingAuthoringMeta) = findBestExpander(remainingAuthoringMeta);\n                        seeds[depth] = seed;\n                        expansions[depth] = expansion;\n                        depth++;\n                    }\n                }\n\n                uint256 parseMetaLength =\n                    META_PREFIX_SIZE + depth * META_EXPANSION_SIZE + authoringMeta.length * META_ITEM_SIZE;\n                parseMeta = new bytes(parseMetaLength);\n                assembly (\"memory-safe\") {\n                    mstore8(add(parseMeta, 0x20), depth)\n                }\n                for (uint256 j = 0; j < depth; j++) {\n                    assembly (\"memory-safe\") {\n                        // Write each seed immediately before its expansion.\n                        let seedWriteAt := add(add(parseMeta, 0x21), mul(0x21, j))\n                        mstore8(seedWriteAt, mload(add(seeds, add(0x20, mul(0x20, j)))))\n                        mstore(add(seedWriteAt, 1), mload(add(expansions, add(0x20, mul(0x20, j)))))\n                    }\n                }\n\n                {\n                    uint256 dataOffset = META_PREFIX_SIZE + META_ITEM_SIZE + depth * META_EXPANSION_SIZE;\n                    assembly (\"memory-safe\") {\n                        dataStart := add(parseMeta, dataOffset)\n                    }\n                }\n            }\n\n            // Write words.\n            for (uint256 k = 0; k < authoringMeta.length; k++) {\n                uint256 s = 0;\n                uint256 cumulativePos = 0;\n                while (true) {\n                    uint256 toWrite;\n                    uint256 writeAt;\n\n                    // Need some careful scoping here to avoid stack too deep.\n                    {\n                        uint256 expansion = expansions[s];\n\n                        uint256 hashed;\n                        {\n                            uint256 shifted;\n                            (shifted, hashed) = wordBitmapped(seeds[s], authoringMeta[k].word);\n\n                            uint256 metaItemSize = META_ITEM_SIZE;\n                            uint256 pos = LibCtPop.ctpop(expansion & (shifted - 1)) + cumulativePos;\n                            assembly (\"memory-safe\") {\n                                writeAt := add(dataStart, mul(pos, metaItemSize))\n                            }\n                        }\n\n                        {\n                            uint256 wordFingerprint = hashed & FINGERPRINT_MASK;\n                            uint256 posFingerprint;\n                            assembly (\"memory-safe\") {\n                                posFingerprint := mload(writeAt)\n                            }\n                            posFingerprint &= FINGERPRINT_MASK;\n                            if (posFingerprint != 0) {\n                                if (posFingerprint == wordFingerprint) {\n                                    revert DuplicateFingerprint();\n                                }\n                                // Collision, try next expansion.\n                                s++;\n                                cumulativePos = cumulativePos + LibCtPop.ctpop(expansion);\n                                continue;\n                            }\n                            // Not collision, prepare the write with the\n                            // fingerprint and index.\n                            toWrite = wordFingerprint | (k << 0x18);\n                        }\n                    }\n\n                    uint256 mask = ~META_ITEM_MASK;\n                    assembly (\"memory-safe\") {\n                        mstore(writeAt, or(and(mload(writeAt), mask), toWrite))\n                    }\n                    // We're done with this word.\n                    break;\n                }\n            }\n        }\n    }\n\n    /// Given the parse meta and a word, return the index and io fn pointer for\n    /// the word. If the word is not found, then `exists` will be false. The\n    /// caller MUST check `exists` before using the other return values.\n    /// @param state The parser state.\n    /// @param word The word to lookup.\n    /// @return True if the word exists in the parse meta.\n    /// @return The index of the word in the parse meta.\n    function lookupWord(ParseState memory state, bytes32 word) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 dataStart;\n            uint256 cursor;\n            uint256 end;\n            {\n                uint256 metaExpansionSize = META_EXPANSION_SIZE;\n                uint256 metaItemSize = META_ITEM_SIZE;\n                bytes memory meta = state.meta;\n                assembly (\"memory-safe\") {\n                    // Read depth from first meta byte.\n                    cursor := add(meta, 1)\n                    let depth := and(mload(cursor), 0xFF)\n                    // 33 bytes per depth\n                    end := add(cursor, mul(depth, metaExpansionSize))\n                    dataStart := add(end, metaItemSize)\n                }\n            }\n\n            uint256 cumulativeCt = 0;\n            while (cursor < end) {\n                uint256 expansion;\n                uint256 posData;\n                uint256 wordFingerprint;\n                // Lookup the data at pos.\n                {\n                    uint256 seed;\n                    assembly (\"memory-safe\") {\n                        cursor := add(cursor, 1)\n                        seed := and(mload(cursor), 0xFF)\n                        cursor := add(cursor, 0x20)\n                        expansion := mload(cursor)\n                    }\n\n                    (uint256 shifted, uint256 hashed) = wordBitmapped(seed, word);\n                    uint256 pos = LibCtPop.ctpop(expansion & (shifted - 1)) + cumulativeCt;\n                    wordFingerprint = hashed & FINGERPRINT_MASK;\n                    uint256 metaItemSize = META_ITEM_SIZE;\n                    assembly (\"memory-safe\") {\n                        posData := mload(add(dataStart, mul(pos, metaItemSize)))\n                    }\n                }\n\n                // Match\n                if (wordFingerprint == posData & FINGERPRINT_MASK) {\n                    uint256 index;\n                    assembly (\"memory-safe\") {\n                        index := byte(28, posData)\n                    }\n                    return (true, index);\n                } else {\n                    cumulativeCt += LibCtPop.ctpop(expansion);\n                }\n            }\n            return (false, 0);\n        }\n    }\n}\n"
      },
      "src/lib/parse/LibParseOperand.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {\n    ExpectedOperand,\n    UnclosedOperand,\n    OperandOverflow,\n    OperandValuesOverflow,\n    UnexpectedOperand,\n    UnexpectedOperandValue\n} from \"../../error/ErrParse.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {LibParse} from \"./LibParse.sol\";\nimport {LibParseLiteral} from \"./literal/LibParseLiteral.sol\";\nimport {CMASK_OPERAND_END, CMASK_WHITESPACE, CMASK_OPERAND_START} from \"./LibParseCMask.sol\";\nimport {ParseState, OPERAND_VALUES_LENGTH, FSM_YANG_MASK} from \"./LibParseState.sol\";\nimport {LibParseError} from \"./LibParseError.sol\";\nimport {LibParseInterstitial} from \"./LibParseInterstitial.sol\";\n\nlibrary LibParseOperand {\n    using LibParseError for ParseState;\n    using LibParseLiteral for ParseState;\n    using LibParseOperand for ParseState;\n    using LibParseInterstitial for ParseState;\n\n    function parseOperand(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        uint256 char;\n        assembly (\"memory-safe\") {\n            //slither-disable-next-line incorrect-shift\n            char := shl(byte(0, mload(cursor)), 1)\n        }\n\n        // Reset operand values to length 0 to avoid any previous values bleeding\n        // into processing this operand.\n        uint256[] memory operandValues = state.operandValues;\n        assembly (\"memory-safe\") {\n            mstore(operandValues, 0)\n        }\n\n        // There may not be an operand. Only process if there is.\n        if (char == CMASK_OPERAND_START) {\n            // Move past the opening character.\n            ++cursor;\n            // Let the state be yin so we can parse literals.\n            state.fsm &= ~FSM_YANG_MASK;\n\n            // Load the next char.\n            assembly (\"memory-safe\") {\n                //slither-disable-next-line incorrect-shift\n                char := shl(byte(0, mload(cursor)), 1)\n            }\n            uint256 i = 0;\n            bool success = false;\n            while (cursor < end) {\n                // Load the next char.\n                assembly (\"memory-safe\") {\n                    //slither-disable-next-line incorrect-shift\n                    char := shl(byte(0, mload(cursor)), 1)\n                }\n\n                // Handle any whitespace.\n                // We DO NOT currently support full interstitial parsing here.\n                if (char & CMASK_WHITESPACE != 0) {\n                    // Move past the whitespace.\n                    cursor = state.skipWhitespace(cursor, end);\n                }\n                // If the operand has ended break.\n                else if (char & CMASK_OPERAND_END != 0) {\n                    // Move past the operand end.\n                    ++cursor;\n                    success = true;\n                    break;\n                }\n                // Attempt to parse literals if we're not yang.\n                else if (state.fsm & FSM_YANG_MASK == 0) {\n                    // We can't exceed the initial length of the operand values\n                    // that was allocated when the parse state was created.\n                    if (i == OPERAND_VALUES_LENGTH) {\n                        revert OperandValuesOverflow(state.parseErrorOffset(cursor));\n                    }\n                    uint256 value;\n                    (cursor, value) = state.parseLiteral(cursor, end);\n                    // We manipulate the operand values array directly in\n                    // assembly because if we used the Solidity indexing syntax\n                    // it would bounds check against the _current_ length of the\n                    // operand values array, not the length it was when the\n                    // parse state was created. The current length is just\n                    // whatever it happened to be for the last operand that was\n                    // parsed, so it's not useful for us here.\n                    assembly (\"memory-safe\") {\n                        mstore(add(operandValues, add(0x20, mul(i, 0x20))), value)\n                    }\n                    // Set yang so we don't attempt to parse a literal straight\n                    // off the back of this literal without some whitespace.\n                    state.fsm |= FSM_YANG_MASK;\n                    ++i;\n                }\n                // Something failed here so let's say the author forgot to close\n                // the operand, which is a little arbitrary but at least it's\n                // a consistent error.\n                else {\n                    revert UnclosedOperand(state.parseErrorOffset(cursor));\n                }\n            }\n            if (!success) {\n                revert UnclosedOperand(state.parseErrorOffset(cursor));\n            }\n            assembly (\"memory-safe\") {\n                mstore(operandValues, i)\n            }\n        }\n\n        return cursor;\n    }\n\n    /// Standard dispatch for handling an operand after it is parsed, using the\n    /// encoded function pointers on the current parse state. Requires that the\n    /// word index has been looked up by the parser, exists, and the literal\n    /// values have all been parsed out of the operand string. In the case of\n    /// the main parser this will all be done inline, but in the case of a sub\n    /// parser the literal extraction will be done first, then the word lookup\n    /// will have to be done by the sub parser, alongside the values provided\n    /// by the main parser.\n    function handleOperand(ParseState memory state, uint256 wordIndex) internal pure returns (Operand) {\n        function (uint256[] memory) internal pure returns (Operand) handler;\n        bytes memory handlers = state.operandHandlers;\n        assembly (\"memory-safe\") {\n            // There is no bounds check here because the indexes are calcualted\n            // by the parser itself, NOT provided by the user. Therefore the\n            // scope of corrupt data is limited to a bug in the parser itself,\n            // which can and should have direct test coverage.\n            handler := and(mload(add(handlers, add(2, mul(wordIndex, 2)))), 0xFFFF)\n        }\n        return handler(state.operandValues);\n    }\n\n    function handleOperandDisallowed(uint256[] memory values) internal pure returns (Operand) {\n        if (values.length != 0) {\n            revert UnexpectedOperand();\n        }\n        return Operand.wrap(0);\n    }\n\n    function handleOperandDisallowedAlwaysOne(uint256[] memory values) internal pure returns (Operand) {\n        if (values.length != 0) {\n            revert UnexpectedOperand();\n        }\n        return Operand.wrap(1);\n    }\n\n    /// There must be one or zero values. The fallback is 0 if nothing is\n    /// provided, else the provided value MUST fit in two bytes and is used as\n    /// is.\n    function handleOperandSingleFull(uint256[] memory values) internal pure returns (Operand operand) {\n        // Happy path at the top for efficiency.\n        if (values.length == 1) {\n            assembly (\"memory-safe\") {\n                operand := mload(add(values, 0x20))\n            }\n            if (Operand.unwrap(operand) > uint256(type(uint16).max)) {\n                revert OperandOverflow();\n            }\n        } else if (values.length == 0) {\n            operand = Operand.wrap(0);\n        } else {\n            revert UnexpectedOperandValue();\n        }\n    }\n\n    /// There must be exactly one value. There is no default fallback.\n    function handleOperandSingleFullNoDefault(uint256[] memory values) internal pure returns (Operand operand) {\n        // Happy path at the top for efficiency.\n        if (values.length == 1) {\n            assembly (\"memory-safe\") {\n                operand := mload(add(values, 0x20))\n            }\n            if (Operand.unwrap(operand) > uint256(type(uint16).max)) {\n                revert OperandOverflow();\n            }\n        } else if (values.length == 0) {\n            revert ExpectedOperand();\n        } else {\n            revert UnexpectedOperandValue();\n        }\n    }\n\n    /// There must be exactly two values. There is no default fallback. Each\n    /// value MUST fit in one byte and is used as is.\n    function handleOperandDoublePerByteNoDefault(uint256[] memory values) internal pure returns (Operand operand) {\n        // Happy path at the top for efficiency.\n        if (values.length == 2) {\n            uint256 a;\n            uint256 b;\n            assembly (\"memory-safe\") {\n                a := mload(add(values, 0x20))\n                b := mload(add(values, 0x40))\n            }\n            if (a > type(uint8).max || b > type(uint8).max) {\n                revert OperandOverflow();\n            }\n            operand = Operand.wrap(a | (b << 8));\n        } else if (values.length < 2) {\n            revert ExpectedOperand();\n        } else {\n            revert UnexpectedOperandValue();\n        }\n    }\n\n    /// 8 bit value then maybe 1 bit flag then maybe 1 bit flag. Fallback to 0\n    /// for both flags if not provided.\n    function handleOperand8M1M1(uint256[] memory values) internal pure returns (Operand operand) {\n        // Happy path at the top for efficiency.\n        uint256 length = values.length;\n        if (length >= 1 && length <= 3) {\n            uint256 a;\n            uint256 b;\n            uint256 c;\n            assembly (\"memory-safe\") {\n                a := mload(add(values, 0x20))\n            }\n\n            if (length >= 2) {\n                assembly (\"memory-safe\") {\n                    b := mload(add(values, 0x40))\n                }\n            } else {\n                b = 0;\n            }\n\n            if (length == 3) {\n                assembly (\"memory-safe\") {\n                    c := mload(add(values, 0x60))\n                }\n            } else {\n                c = 0;\n            }\n\n            if (a > type(uint8).max || b > 1 || c > 1) {\n                revert OperandOverflow();\n            }\n\n            operand = Operand.wrap(a | (b << 8) | (c << 9));\n        } else if (length == 0) {\n            revert ExpectedOperand();\n        } else {\n            revert UnexpectedOperandValue();\n        }\n    }\n\n    /// 2x maybe 1 bit flags. Fallback to 0 for both flags if not provided.\n    function handleOperandM1M1(uint256[] memory values) internal pure returns (Operand operand) {\n        // Happy path at the top for efficiency.\n        uint256 length = values.length;\n        if (length < 3) {\n            uint256 a;\n            uint256 b;\n\n            if (length >= 1) {\n                assembly (\"memory-safe\") {\n                    a := mload(add(values, 0x20))\n                }\n            } else {\n                a = 0;\n            }\n\n            if (length == 2) {\n                assembly (\"memory-safe\") {\n                    b := mload(add(values, 0x40))\n                }\n            } else {\n                b = 0;\n            }\n\n            if (a > 1 || b > 1) {\n                revert OperandOverflow();\n            }\n\n            operand = Operand.wrap(a | (b << 1));\n        } else {\n            revert UnexpectedOperandValue();\n        }\n    }\n}\n"
      },
      "lib/rain.interpreter.interface/src/interface/IInterpreterV2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {EncodedDispatch, StateNamespace, Operand, DEFAULT_STATE_NAMESPACE} from \"./deprecated/IInterpreterV1.sol\";\nimport {FullyQualifiedNamespace, IInterpreterStoreV2} from \"./IInterpreterStoreV2.sol\";\n\n/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`\n/// should implement an opcode that reads from the stack by index as opcode `0`.\nuint256 constant OPCODE_STACK = 0;\n\n/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`\n/// should implement an opcode that reads constants by index as opcode `1`.\nuint256 constant OPCODE_CONSTANT = 1;\n\n/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`\n/// should implement an opcode that calls externs by index as opcode `2`.\nuint256 constant OPCODE_EXTERN = 2;\n\n/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`\n/// should implement an opcode that reads from the context grid as <column row>\n/// as opcode `3`.\nuint256 constant OPCODE_CONTEXT = 3;\n\n/// @dev For maximum compatibility with opcode lists, the `IInterpreterV2`\n/// should implement the opcode for locally unknown words that need sub parsing\n/// as opcode `255`.\nuint256 constant OPCODE_UNKNOWN = 0xFF;\n\n/// @dev The index of a source within a deployed expression that can be evaluated\n/// by an `IInterpreterV2`. MAY be an entrypoint or the index of a source called\n/// internally such as by the `call` opcode.\ntype SourceIndexV2 is uint256;\n\n/// @title IInterpreterV2\n/// Interface into a standard interpreter that supports:\n///\n/// - evaluating `view` logic deployed onchain by an `IExpressionDeployerV1`\n/// - receiving arbitrary `uint256[][]` supporting context to be made available\n///   to the evaluated logic\n/// - handling subsequent state changes in bulk in response to evaluated logic\n/// - namespacing state changes according to the caller's preferences to avoid\n///   unwanted key collisions\n/// - exposing its internal function pointers to support external precompilation\n///   of logic for more gas efficient runtime evaluation by the interpreter\n///\n/// The interface is designed to be stable across many versions and\n/// implementations of an interpreter, balancing minimalism with features\n/// required for a general purpose onchain interpreted compute environment.\n///\n/// The security model of an interpreter is that it MUST be resilient to\n/// malicious expressions even if they dispatch arbitrary internal function\n/// pointers during an eval. The interpreter MAY return garbage or exhibit\n/// undefined behaviour or error during an eval, _provided that no state changes\n/// are persisted_ e.g. in storage, such that only the caller that specifies the\n/// malicious expression can be negatively impacted by the result. In turn, the\n/// caller must guard itself against arbitrarily corrupt/malicious reverts and\n/// return values from any interpreter that it requests an expression from. And\n/// so on and so forth up to the externally owned account (EOA) who signs the\n/// transaction and agrees to a specific combination of contracts, expressions\n/// and interpreters, who can presumably make an informed decision about which\n/// ones to trust to get the job done.\n///\n/// The state changes for an interpreter are expected to be produced by an\n/// `eval2` and passed to the `IInterpreterStoreV1` returned by the eval, as-is\n/// by the caller, after the caller has had an opportunity to apply their own\n/// intermediate logic such as reentrancy defenses against malicious\n/// interpreters. The interpreter is free to structure the state changes however\n/// it wants but MUST guard against the calling contract corrupting the changes\n/// between `eval2` and `set`. For example a store could sandbox storage writes\n/// per-caller so that a malicious caller can only damage their own state\n/// changes, while honest callers respect, benefit from and are protected by the\n/// interpreter store's state change handling.\n///\n/// The two step eval-state model allows evaluation to be read-only which\n/// provides security guarantees for the caller such as no stateful reentrancy,\n/// either from the interpreter or some contract interface used by some word,\n/// while still allowing for storage writes. As the storage writes happen on the\n/// interpreter rather than the caller (c.f. delegate call) the caller DOES NOT\n/// need to trust the interpreter, which allows for permissionless selection of\n/// interpreters by end users. Delegate call always implies an admin key on the\n/// caller because the delegatee contract can write arbitrarily to the state of\n/// the delegator, which severely limits the generality of contract composition.\ninterface IInterpreterV2 {\n    /// Exposes the function pointers as `uint16` values packed into a single\n    /// `bytes` in the same order as they would be indexed into by opcodes. For\n    /// example, if opcode `2` should dispatch function at position `0x1234` then\n    /// the start of the returned bytes would be `0xXXXXXXXX1234` where `X` is\n    /// a placeholder for the function pointers of opcodes `0` and `1`.\n    ///\n    /// `IExpressionDeployerV3` contracts use these function pointers to\n    /// \"compile\" the expression into something that an interpreter can dispatch\n    /// directly without paying gas to lookup the same at runtime. As the\n    /// validity of any integrity check and subsequent dispatch is highly\n    /// sensitive to both the function pointers and overall bytecode of the\n    /// interpreter, `IExpressionDeployerV3` contracts SHOULD implement guards\n    /// against accidentally being deployed onchain paired against an unknown\n    /// interpreter. It is very easy for an apparent compatible pairing to be\n    /// subtly and critically incompatible due to addition/removal/reordering of\n    /// opcodes and compiler optimisations on the interpreter bytecode.\n    ///\n    /// This MAY return different values during construction vs. all other times\n    /// after the interpreter has been successfully deployed onchain. DO NOT rely\n    /// on function pointers reported during contract construction.\n    function functionPointers() external view returns (bytes calldata);\n\n    /// The raison d'etre for an interpreter. Given some expression and per-call\n    /// additional contextual data, produce a stack of results and a set of state\n    /// changes that the caller MAY OPTIONALLY pass back to be persisted by a\n    /// call to `IInterpreterStoreV1.set`.\n    ///\n    /// There are two key differences between `eval` and `eval2`:\n    /// - `eval` was ambiguous about whether the top value of the final stack is\n    /// the first or last item of the array. `eval2` is unambiguous in that the\n    /// top of the stack MUST be the first item in the array.\n    /// - `eval2` allows the caller to specify inputs to the entrypoint stack of\n    /// the expression. This allows the `eval` and `offchainDebugEval` functions\n    /// to be merged into a single function that can be used for both onchain and\n    /// offchain evaluation. For example, the caller can simulate \"internal\"\n    /// calls by specifying the inputs to the entrypoint stack of the expression\n    /// as the outputs of some other expression. Legacy behaviour can be achieved\n    /// by passing an empty array for `inputs`.\n    ///\n    /// @param store The storage contract that the returned key/value pairs\n    /// MUST be passed to IF the calling contract is in a non-static calling\n    /// context. Static calling contexts MUST pass `address(0)`.\n    /// @param namespace The fully qualified namespace that will be used by the\n    /// interpreter at runtime in order to perform gets on the underlying store.\n    /// @param dispatch All the information required for the interpreter to load\n    /// an expression, select an entrypoint and return the values expected by the\n    /// caller. The interpreter MAY encode dispatches differently to\n    /// `LibEncodedDispatch` but this WILL negatively impact compatibility for\n    /// calling contracts that hardcode the encoding logic.\n    /// @param context A 2-dimensional array of data that can be indexed into at\n    /// runtime by the interpreter. The calling contract is responsible for\n    /// ensuring the authenticity and completeness of context data. The\n    /// interpreter MUST revert at runtime if an expression attempts to index\n    /// into some context value that is not provided by the caller. This implies\n    /// that context reads cannot be checked for out of bounds reads at deploy\n    /// time, as the runtime context MAY be provided in a different shape to what\n    /// the expression is expecting.\n    /// @param inputs The inputs to the entrypoint stack of the expression. MAY\n    /// be empty if the caller prefers to specify all inputs via. context.\n    /// @return stack The list of values produced by evaluating the expression.\n    /// MUST NOT be longer than the maximum length specified by `dispatch`, if\n    /// applicable. MUST be ordered such that the top of the stack is the FIRST\n    /// item in the array.\n    /// @return writes A list of values to be processed by a store. Most likely\n    /// will be pairwise key/value items but this is not strictly required if\n    /// some store expects some other format.\n    function eval2(\n        IInterpreterStoreV2 store,\n        FullyQualifiedNamespace namespace,\n        EncodedDispatch dispatch,\n        uint256[][] calldata context,\n        uint256[] calldata inputs\n    ) external view returns (uint256[] calldata stack, uint256[] calldata writes);\n}\n"
      },
      "src/lib/parse/LibParseStackName.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ParseState} from \"./LibParseState.sol\";\n\nlibrary LibParseStackName {\n    /// Push a word onto the stack name stack.\n    /// @return exists Whether the word already existed.\n    /// @return index The new index after the word was pushed. Will be unchanged\n    /// if the word already existed.\n    function pushStackName(ParseState memory state, bytes32 word) internal pure returns (bool exists, uint256 index) {\n        unchecked {\n            (exists, index) = stackNameIndex(state, word);\n            if (!exists) {\n                uint256 fingerprint;\n                uint256 ptr;\n                uint256 oldStackNames = state.stackNames;\n                assembly (\"memory-safe\") {\n                    ptr := mload(0x40)\n                    mstore(ptr, word)\n                    fingerprint := and(keccak256(ptr, 0x20), not(0xFFFFFFFF))\n                    mstore(ptr, oldStackNames)\n                    mstore(0x40, add(ptr, 0x20))\n                }\n                // Add the start of line height to the LHS line parse count.\n                uint256 stackLHSIndex = state.topLevel1 & 0xFF;\n                state.stackNames = fingerprint | (stackLHSIndex << 0x10) | ptr;\n                index = stackLHSIndex + 1;\n            }\n        }\n    }\n\n    /// Retrieve the index of a previously pushed stack name.\n    function stackNameIndex(ParseState memory state, bytes32 word) internal pure returns (bool exists, uint256 index) {\n        uint256 fingerprint;\n        uint256 stackNames = state.stackNames;\n        uint256 stackNameBloom = state.stackNameBloom;\n        uint256 bloom;\n        assembly (\"memory-safe\") {\n            mstore(0, word)\n            fingerprint := shr(0x20, keccak256(0, 0x20))\n            //slither-disable-next-line incorrect-shift\n            bloom := shl(and(fingerprint, 0xFF), 1)\n\n            // If the bloom matches then maybe the stack name is in the stack.\n            if and(bloom, stackNameBloom) {\n                for { let ptr := and(stackNames, 0xFFFF) } iszero(iszero(ptr)) {\n                    stackNames := mload(ptr)\n                    ptr := and(stackNames, 0xFFFF)\n                } {\n                    if eq(fingerprint, shr(0x20, stackNames)) {\n                        exists := true\n                        index := and(shr(0x10, stackNames), 0xFFFF)\n                        break\n                    }\n                }\n            }\n        }\n        state.stackNameBloom = bloom | stackNameBloom;\n    }\n}\n"
      },
      "src/error/ErrParse.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572\ncontract ErrParse {}\n\n/// Thrown when parsing a source string and an operand opening `<` paren is found\n/// somewhere that we don't expect it or can't handle it.\nerror UnexpectedOperand();\n\n/// Thrown when there are more operand values in the operand than the handler\n/// is expecting.\nerror UnexpectedOperandValue();\n\n/// Thrown when parsing an operand and some required component of the operand is\n/// not found in the source string.\nerror ExpectedOperand();\n\n/// Thrown when parsing an operand and the literal in the source string is too\n/// large to fit in the bits allocated for it in the operand.\nerror OperandOverflow();\n\n/// Thrown when the number of values encountered in a single operand parsing is\n/// longer than the memory allocated to hold them.\n/// @param offset The offset in the source string where the error occurred.\nerror OperandValuesOverflow(uint256 offset);\n\n/// Thrown when parsing an operand and the closing `>` paren is not found.\n/// @param offset The offset in the source string where the error occurred.\nerror UnclosedOperand(uint256 offset);\n\n/// The parser tried to bound an unsupported literal that we have no type for.\nerror UnsupportedLiteralType(uint256 offset);\n\n/// Encountered a string literal that is larger than supported.\nerror StringTooLong(uint256 offset);\n\n/// Encountered a string that does not have a valid end, e.g. we found some char\n/// that was not printable ASCII and had to stop.\nerror UnclosedStringLiteral(uint256 offset);\n\n/// Encountered a literal that is larger than supported.\nerror HexLiteralOverflow(uint256 offset);\n\n/// Encountered a zero length hex literal.\nerror ZeroLengthHexLiteral(uint256 offset);\n\n/// Encountered an odd sized hex literal.\nerror OddLengthHexLiteral(uint256 offset);\n\n/// Encountered a hex literal with an invalid character.\nerror MalformedHexLiteral(uint256 offset);\n\n/// Encountered a decimal literal that is larger than supported.\nerror DecimalLiteralOverflow(uint256 offset);\n\n/// Encountered a decimal literal with an exponent that has too many or no\n/// digits.\nerror MalformedExponentDigits(uint256 offset);\n\n/// Encountered a zero length decimal literal.\nerror ZeroLengthDecimal(uint256 offset);\n\n/// The expression does not finish with a semicolon (EOF).\nerror MissingFinalSemi(uint256 offset);\n\n/// Enountered an unexpected character on the LHS.\nerror UnexpectedLHSChar(uint256 offset);\n\n/// Encountered an unexpected character on the RHS.\nerror UnexpectedRHSChar(uint256 offset);\n\n/// More specific version of UnexpectedRHSChar where we specifically expected\n/// a left paren but got some other char.\nerror ExpectedLeftParen(uint256 offset);\n\n/// Encountered a right paren without a matching left paren.\nerror UnexpectedRightParen(uint256 offset);\n\n/// Encountered an unclosed left paren.\nerror UnclosedLeftParen(uint256 offset);\n\n/// Encountered a comment outside the interstitial space between lines.\nerror UnexpectedComment(uint256 offset);\n\n/// Encountered a comment that never ends.\nerror UnclosedComment(uint256 offset);\n\n/// Encountered a comment start sequence that is malformed.\nerror MalformedCommentStart(uint256 offset);\n\n/// @dev Thrown when a stack name is duplicated. Shadowing in all forms is\n/// disallowed in Rainlang.\nerror DuplicateLHSItem(uint256 errorOffset);\n\n/// Encountered too many LHS items.\nerror ExcessLHSItems(uint256 offset);\n\n/// Encountered inputs where they can't be handled.\nerror NotAcceptingInputs(uint256 offset);\n\n/// Encountered too many RHS items.\nerror ExcessRHSItems(uint256 offset);\n\n/// Encountered a word that is longer than 32 bytes.\nerror WordSize(string word);\n\n/// Parsed a word that is not in the meta.\nerror UnknownWord();\n\n/// The parser exceeded the maximum number of sources that it can build.\nerror MaxSources();\n\n/// The parser encountered a dangling source. This is a bug in the parser.\nerror DanglingSource();\n\n/// The parser moved past the end of the data.\nerror ParserOutOfBounds();\n\n/// The parser encountered a stack deeper than it can process in the memory\n/// region allocated for stack names.\nerror ParseStackOverflow();\n\n/// The parser encountered a stack underflow.\nerror ParseStackUnderflow();\n\n/// The parser encountered a paren group deeper than it can process in the\n/// memory region allocated for paren tracking.\nerror ParenOverflow();\n\n/// The parser did not find any whitespace after the pragma keyword.\nerror NoWhitespaceAfterUsingWordsFrom(uint256 offset);\n\n/// The parser encountered a literal that it cannot use as a sub parser.\nerror InvalidSubParser(uint256 offset);\n\n/// The parser encountered an unclosed sub parsed literal.\nerror UnclosedSubParseableLiteral(uint256 offset);\n\n/// The parser encountered a sub parseable literal with a missing dispatch.\nerror SubParseableMissingDispatch(uint256 offset);\n\n/// The sub parser returned some bytecode that the main parser could not\n/// understand.\nerror BadSubParserResult(bytes bytecode);\n\n/// Thrown when there are more than 16 inputs or outputs for a given opcode.\nerror OpcodeIOOverflow(uint256 offset);\n"
      },
      "src/lib/parse/LibParsePragma.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibParseState, ParseState} from \"./LibParseState.sol\";\nimport {CMASK_WHITESPACE, CMASK_LITERAL_HEX_DISPATCH_START} from \"./LibParseCMask.sol\";\nimport {NoWhitespaceAfterUsingWordsFrom} from \"../../error/ErrParse.sol\";\nimport {LibParseError} from \"./LibParseError.sol\";\nimport {LibParseInterstitial} from \"./LibParseInterstitial.sol\";\nimport {LibParseLiteral} from \"./literal/LibParseLiteral.sol\";\n\nbytes constant PRAGMA_KEYWORD_BYTES = bytes(\"using-words-from\");\nbytes32 constant PRAGMA_KEYWORD_BYTES32 = bytes32(PRAGMA_KEYWORD_BYTES);\nuint256 constant PRAGMA_KEYWORD_BYTES_LENGTH = 16;\nbytes32 constant PRAGMA_KEYWORD_MASK = bytes32(~((1 << (32 - PRAGMA_KEYWORD_BYTES_LENGTH) * 8) - 1));\n\nlibrary LibParsePragma {\n    using LibParseError for ParseState;\n    using LibParseInterstitial for ParseState;\n    using LibParseLiteral for ParseState;\n    using LibParseState for ParseState;\n\n    function parsePragma(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        unchecked {\n            // Not-pragma guard.\n            {\n                // There is a pragma if the cursor is pointing exactly at the bytes of\n                // the pragma.\n                bytes32 maybePragma;\n                assembly (\"memory-safe\") {\n                    maybePragma := mload(cursor)\n                }\n                // Bail without modifying the cursor if there's no pragma.\n                if (maybePragma & PRAGMA_KEYWORD_MASK != PRAGMA_KEYWORD_BYTES32) {\n                    return cursor;\n                }\n            }\n\n            {\n                // Move past the pragma keyword.\n                cursor += PRAGMA_KEYWORD_BYTES_LENGTH;\n\n                // Need at least one whitespace char after the pragma keyword.\n                uint256 char;\n                assembly (\"memory-safe\") {\n                    //slither-disable-next-line incorrect-shift\n                    char := shl(byte(0, mload(cursor)), 1)\n                }\n                if (char & CMASK_WHITESPACE == 0) {\n                    revert NoWhitespaceAfterUsingWordsFrom(state.parseErrorOffset(cursor));\n                }\n                ++cursor;\n            }\n\n            while (cursor < end) {\n                // It's fine to add comments for each pragma address.\n                // This also has the effect of moving past the interstitial after\n                // the last address as we don't break til just below.\n                cursor = state.parseInterstitial(cursor, end);\n\n                // Try to parse a literal and treat it as an address.\n                bool success;\n                uint256 value;\n                (success, cursor, value) = state.tryParseLiteral(cursor, end);\n                // If we didn't parse a literal, we're done with the pragma.\n                if (!success) {\n                    break;\n                } else {\n                    state.pushSubParser(cursor, value);\n                }\n            }\n\n            return cursor;\n        }\n    }\n}\n"
      },
      "src/lib/parse/LibParseInterstitial.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {FSM_YANG_MASK, ParseState} from \"./LibParseState.sol\";\nimport {\n    CMASK_COMMENT_HEAD,\n    CMASK_WHITESPACE,\n    COMMENT_END_SEQUENCE,\n    COMMENT_START_SEQUENCE,\n    CMASK_COMMENT_END_SEQUENCE_END\n} from \"./LibParseCMask.sol\";\nimport {ParserOutOfBounds, MalformedCommentStart, UnclosedComment} from \"../../error/ErrParse.sol\";\nimport {LibParseError} from \"./LibParseError.sol\";\nimport {LibParse} from \"./LibParse.sol\";\n\nlibrary LibParseInterstitial {\n    using LibParse for ParseState;\n    using LibParseError for ParseState;\n    using LibParseInterstitial for ParseState;\n\n    /// The cursor currently points at the head of a comment. We need to skip\n    /// over all data until we find the end of the comment. This MAY REVERT if\n    /// the comment is malformed, e.g. if the comment doesn't start with `/*`.\n    /// @param state The parser state.\n    /// @param cursor The current cursor position.\n    /// @return The new cursor position.\n    function skipComment(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        // Set yang for comments to force a little breathing room between\n        // comments and the next item.\n        state.fsm |= FSM_YANG_MASK;\n\n        // We're going to ignore overflow here because if either cursor or\n        // end is anywhere near uint256 max something went very wrong\n        // elsewhere already.\n        unchecked {\n            // It's an error if we can't fit the comment sequences in the\n            // remaining data to parse.\n            if (cursor + 4 > end) {\n                revert UnclosedComment(state.parseErrorOffset(cursor));\n            }\n\n            // First check the comment opening sequence is not malformed.\n            uint256 startSequence;\n            assembly (\"memory-safe\") {\n                startSequence := shr(0xf0, mload(cursor))\n            }\n            if (startSequence != COMMENT_START_SEQUENCE) {\n                revert MalformedCommentStart(state.parseErrorOffset(cursor));\n            }\n\n            // Move past the start sequence.\n            // The 3rd character can never be the end of the comment.\n            // Consider the string /*/ which is not a valid comment.\n            cursor += 3;\n\n            bool foundEnd = false;\n            while (cursor < end) {\n                uint256 charByte;\n                assembly (\"memory-safe\") {\n                    charByte := byte(0, mload(cursor))\n                }\n                if (charByte == CMASK_COMMENT_END_SEQUENCE_END) {\n                    // Maybe this is the end of the comment.\n                    // Check the sequence.\n                    uint256 endSequence;\n                    assembly (\"memory-safe\") {\n                        endSequence := shr(0xf0, mload(sub(cursor, 1)))\n                    }\n                    if (endSequence == COMMENT_END_SEQUENCE) {\n                        // We found the end of the comment.\n                        // Move past the end sequence and stop looping.\n                        ++cursor;\n                        foundEnd = true;\n                        break;\n                    }\n                }\n                ++cursor;\n            }\n\n            // If we didn't find the end of the comment, it's an error.\n            if (!foundEnd) {\n                revert UnclosedComment(state.parseErrorOffset(cursor));\n            }\n\n            return cursor;\n        }\n    }\n\n    function skipWhitespace(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        unchecked {\n            // Set ying as we now open to possibilities.\n            state.fsm &= ~FSM_YANG_MASK;\n            return LibParse.skipMask(cursor, end, CMASK_WHITESPACE);\n        }\n    }\n\n    function parseInterstitial(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256) {\n        while (cursor < end) {\n            uint256 char;\n            assembly (\"memory-safe\") {\n                //slither-disable-next-line incorrect-shift\n                char := shl(byte(0, mload(cursor)), 1)\n            }\n            if (char & CMASK_WHITESPACE > 0) {\n                cursor = state.skipWhitespace(cursor, end);\n            } else if (char & CMASK_COMMENT_HEAD > 0) {\n                cursor = state.skipComment(cursor, end);\n            } else {\n                break;\n            }\n        }\n        return cursor;\n    }\n}\n"
      },
      "src/lib/parse/LibParseError.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ParseState} from \"./LibParseState.sol\";\n\nlibrary LibParseError {\n    function parseErrorOffset(ParseState memory state, uint256 cursor) internal pure returns (uint256 offset) {\n        bytes memory data = state.data;\n        assembly (\"memory-safe\") {\n            offset := sub(cursor, add(data, 0x20))\n        }\n    }\n}\n"
      },
      "src/lib/parse/LibSubParse.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibParseState, ParseState} from \"./LibParseState.sol\";\nimport {\n    OPCODE_UNKNOWN,\n    OPCODE_EXTERN,\n    OPCODE_CONSTANT,\n    OPCODE_CONTEXT,\n    Operand\n} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {LibBytecode, Pointer} from \"rain.interpreter.interface/lib/bytecode/LibBytecode.sol\";\nimport {ISubParserV2, COMPATIBLITY_V3} from \"rain.interpreter.interface/interface/ISubParserV2.sol\";\nimport {BadSubParserResult, UnknownWord, UnsupportedLiteralType} from \"../../error/ErrParse.sol\";\nimport {LibExtern, EncodedExternDispatch} from \"../extern/LibExtern.sol\";\nimport {IInterpreterExternV3} from \"rain.interpreter.interface/interface/IInterpreterExternV3.sol\";\nimport {ExternDispatchConstantsHeightOverflow} from \"../../error/ErrSubParse.sol\";\nimport {LibMemCpy} from \"rain.solmem/lib/LibMemCpy.sol\";\nimport {LibParseError} from \"./LibParseError.sol\";\n\nlibrary LibSubParse {\n    using LibParseState for ParseState;\n    using LibParseError for ParseState;\n\n    /// Sub parse a word into a context grid position.\n    function subParserContext(uint256 column, uint256 row)\n        internal\n        pure\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        bytes memory bytecode;\n        uint256 opIndex = OPCODE_CONTEXT;\n        assembly (\"memory-safe\") {\n            // Allocate the bytecode.\n            // This is an UNALIGNED allocation.\n            bytecode := mload(0x40)\n            mstore(0x40, add(bytecode, 0x24))\n\n            // The caller is responsible for ensuring the column and row are\n            // within `uint8`.\n            mstore8(add(bytecode, 0x23), column)\n            mstore8(add(bytecode, 0x22), row)\n\n            // 0 inputs 1 output.\n            mstore8(add(bytecode, 0x21), 0x10)\n\n            mstore8(add(bytecode, 0x20), opIndex)\n\n            // Write the length of the bytes.\n            mstore(bytecode, 4)\n        }\n\n        uint256[] memory constants;\n        assembly (\"memory-safe\") {\n            constants := mload(0x40)\n            mstore(0x40, add(constants, 0x20))\n            mstore(constants, 0)\n        }\n\n        return (true, bytecode, constants);\n    }\n\n    /// Sub parse a value into the bytecode that will run on the interpreter to\n    /// push the given value onto the stack, using the constant opcode at eval.\n    function subParserConstant(uint256 constantsHeight, uint256 value)\n        internal\n        pure\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        // Build a constant opcode that the interpreter will run itself.\n        bytes memory bytecode;\n        uint256 opIndex = OPCODE_CONSTANT;\n        assembly (\"memory-safe\") {\n            // Allocate the bytecode.\n            // This is an UNALIGNED allocation.\n            bytecode := mload(0x40)\n            mstore(0x40, add(bytecode, 0x24))\n\n            // It's most efficient to store the constants height first, as it\n            // is in theory multibyte (although it's not expected to be).\n            // This also has the effect of zeroing out the inputs, which is what\n            // we want, as long as the main parser respects the constants height\n            // never being more than 2 bytes.\n            mstore(add(bytecode, 4), constantsHeight)\n\n            // 0 inputs 1 output.\n            mstore8(add(bytecode, 0x21), 0x10)\n\n            // Main opcode is constant.\n            mstore8(add(bytecode, 0x20), opIndex)\n\n            // Write the length of the bytes.\n            mstore(bytecode, 4)\n        }\n\n        uint256[] memory constants;\n        assembly (\"memory-safe\") {\n            constants := mload(0x40)\n            mstore(0x40, add(constants, 0x40))\n            mstore(constants, 1)\n            mstore(add(constants, 0x20), value)\n        }\n\n        return (true, bytecode, constants);\n    }\n\n    /// Sub parse a known extern opcode index into the bytecode that will run\n    /// on the interpreter to call the given extern contract. This requires the\n    /// parsing has already matched a word to the extern opcode index, so it\n    /// implies the parse meta has been traversed and the parse index has been\n    /// mapped to an extern opcode index somehow.\n    function subParserExtern(\n        IInterpreterExternV3 extern,\n        uint256 constantsHeight,\n        uint256 ioByte,\n        Operand operand,\n        uint256 opcodeIndex\n    ) internal pure returns (bool, bytes memory, uint256[] memory) {\n        // The constants height is an error check because the main parser can\n        // provide two bytes for it. Everything else is expected to be more\n        // directly controlled by the subparser itself.\n        if (constantsHeight > 0xFFFF) {\n            revert ExternDispatchConstantsHeightOverflow(constantsHeight);\n        }\n        // Build an extern call that dials back into the current contract at eval\n        // time with the current opcode index.\n        bytes memory bytecode;\n        uint256 opIndex = OPCODE_EXTERN;\n        assembly (\"memory-safe\") {\n            // Allocate the bytecode.\n            // This is an UNALIGNED allocation.\n            bytecode := mload(0x40)\n            mstore(0x40, add(bytecode, 0x24))\n            mstore(add(bytecode, 4), constantsHeight)\n            // The IO byte is inputs merged with outputs.\n            mstore8(add(bytecode, 0x21), ioByte)\n            // Main opcode is extern, to call back into current contract.\n            mstore8(add(bytecode, 0x20), opIndex)\n            // The bytes length is 4.\n            mstore(bytecode, 4)\n        }\n\n        uint256 externDispatch = EncodedExternDispatch.unwrap(\n            LibExtern.encodeExternCall(extern, LibExtern.encodeExternDispatch(opcodeIndex, operand))\n        );\n\n        uint256[] memory constants;\n        assembly (\"memory-safe\") {\n            constants := mload(0x40)\n            mstore(0x40, add(constants, 0x40))\n            mstore(constants, 1)\n            mstore(add(constants, 0x20), externDispatch)\n        }\n\n        return (true, bytecode, constants);\n    }\n\n    function subParseWordSlice(ParseState memory state, uint256 cursor, uint256 end) internal pure {\n        unchecked {\n            for (; cursor < end; cursor += 4) {\n                uint256 memoryAtCursor;\n                assembly (\"memory-safe\") {\n                    memoryAtCursor := mload(cursor)\n                }\n                if (memoryAtCursor >> 0xf8 == OPCODE_UNKNOWN) {\n                    uint256 deref = state.subParsers;\n                    while (deref != 0) {\n                        ISubParserV2 subParser = ISubParserV2(address(uint160(deref)));\n                        assembly (\"memory-safe\") {\n                            deref := mload(shr(0xf0, deref))\n                        }\n\n                        // Subparse data is a fixed length header that provides the\n                        // subparser some minimal additional contextual information\n                        // then the rest of the data is the original string that the\n                        // main parser could not understand.\n                        // The header is:\n                        // - 2 bytes: The current constant builder height. MAY be\n                        //   used by the subparser to calculate indexes for the\n                        //   constants it pushes.\n                        // - 1 byte: The IO byte from the unknown op. MAY be used\n                        //   by the subparser to calculate the IO byte for the op\n                        //   it builds.\n                        bytes memory data;\n                        // The operand of the unknown opcode directly points at the\n                        // data that we need to subparse.\n                        assembly (\"memory-safe\") {\n                            data := and(shr(0xe0, memoryAtCursor), 0xFFFF)\n                        }\n                        // We just need to fill in the header.\n                        {\n                            uint256 constantsBuilder = state.constantsBuilder;\n                            assembly (\"memory-safe\") {\n                                let header :=\n                                    shl(\n                                        0xe8,\n                                        or(\n                                            // IO byte is the second byte of the unknown op.\n                                            byte(1, memoryAtCursor),\n                                            // Constants builder height is the low 16 bits.\n                                            shl(8, and(constantsBuilder, 0xFFFF))\n                                        )\n                                    )\n\n                                let headerPtr := add(data, 0x20)\n                                mstore(headerPtr, or(header, and(mload(headerPtr), not(shl(0xe8, 0xFFFFFF)))))\n                            }\n                        }\n\n                        (bool success, bytes memory subBytecode, uint256[] memory subConstants) =\n                            subParser.subParseWord(COMPATIBLITY_V3, data);\n                        if (success) {\n                            // The sub bytecode must be exactly 4 bytes to\n                            // represent an op.\n                            if (subBytecode.length != 4) {\n                                revert BadSubParserResult(subBytecode);\n                            }\n\n                            {\n                                // Copy the sub bytecode over the unknown op.\n                                uint256 mask = 0xFFFFFFFF << 0xe0;\n                                assembly (\"memory-safe\") {\n                                    mstore(\n                                        cursor,\n                                        or(and(memoryAtCursor, not(mask)), and(mload(add(subBytecode, 0x20)), mask))\n                                    )\n                                }\n                            }\n\n                            for (uint256 i; i < subConstants.length; ++i) {\n                                state.pushConstantValue(subConstants[i]);\n                            }\n\n                            // Stop looping over sub parsers now.\n                            break;\n                        }\n                    }\n                }\n\n                // If the op was not replaced, then we need to error because we have\n                // no idea what it is.\n                assembly (\"memory-safe\") {\n                    memoryAtCursor := mload(cursor)\n                }\n                if (memoryAtCursor >> 0xf8 == OPCODE_UNKNOWN) {\n                    revert UnknownWord();\n                }\n            }\n        }\n    }\n\n    function subParseWords(ParseState memory state, bytes memory bytecode)\n        internal\n        pure\n        returns (bytes memory, uint256[] memory)\n    {\n        unchecked {\n            uint256 sourceCount = LibBytecode.sourceCount(bytecode);\n            for (uint256 sourceIndex; sourceIndex < sourceCount; ++sourceIndex) {\n                // Start cursor at the pointer to the source.\n                uint256 cursor = Pointer.unwrap(LibBytecode.sourcePointer(bytecode, sourceIndex)) + 4;\n                uint256 end = cursor + (LibBytecode.sourceOpsCount(bytecode, sourceIndex) * 4);\n                subParseWordSlice(state, cursor, end);\n            }\n            return (bytecode, state.buildConstants());\n        }\n    }\n\n    function subParseLiteral(\n        ParseState memory state,\n        uint256 dispatchStart,\n        uint256 dispatchEnd,\n        uint256 bodyStart,\n        uint256 bodyEnd\n    ) internal pure returns (uint256) {\n        unchecked {\n            // Build the data for the subparser.\n            bytes memory data;\n            {\n                uint256 copyPointer;\n                uint256 dispatchLength = dispatchEnd - dispatchStart;\n                uint256 bodyLength = bodyEnd - bodyStart;\n                {\n                    uint256 dataLength = 2 + dispatchLength + bodyLength;\n                    assembly (\"memory-safe\") {\n                        data := mload(0x40)\n                        mstore(0x40, add(data, add(dataLength, 0x20)))\n                        mstore(add(data, 2), dispatchLength)\n                        mstore(data, dataLength)\n                        copyPointer := add(data, 0x22)\n                    }\n                }\n                LibMemCpy.unsafeCopyBytesTo(Pointer.wrap(dispatchStart), Pointer.wrap(copyPointer), dispatchLength);\n                LibMemCpy.unsafeCopyBytesTo(\n                    Pointer.wrap(bodyStart), Pointer.wrap(copyPointer + dispatchLength), bodyLength\n                );\n            }\n\n            uint256 deref = state.subParsers;\n            while (deref != 0) {\n                ISubParserV2 subParser = ISubParserV2(address(uint160(deref)));\n                assembly (\"memory-safe\") {\n                    deref := mload(shr(0xf0, deref))\n                }\n\n                (bool success, uint256 value) = subParser.subParseLiteral(COMPATIBLITY_V3, data);\n                if (success) {\n                    return value;\n                }\n            }\n\n            revert UnsupportedLiteralType(state.parseErrorOffset(dispatchStart));\n        }\n    }\n\n    function consumeSubParseWordInputData(bytes memory data, bytes memory meta, bytes memory operandHandlers)\n        internal\n        pure\n        returns (uint256 constantsHeight, uint256 ioByte, ParseState memory state)\n    {\n        uint256[] memory operandValues;\n        assembly (\"memory-safe\") {\n            // Pull the header out into EVM stack items.\n            constantsHeight := and(mload(add(data, 2)), 0xFFFF)\n            ioByte := and(mload(add(data, 3)), 0xFF)\n\n            // Mutate the data to no longer have a header.\n            let newLength := and(mload(add(data, 5)), 0xFFFF)\n            data := add(data, 5)\n            mstore(data, newLength)\n            operandValues := add(data, add(newLength, 0x20))\n        }\n        // Literal parsers are empty for the sub parser as the main parser should\n        // be handling all literals in operands. The sub parser handles literal\n        // parsing as a dedicated interface seperately.\n        state = LibParseState.newState(data, meta, operandHandlers, \"\");\n        state.operandValues = operandValues;\n    }\n\n    function consumeSubParseLiteralInputData(bytes memory data)\n        internal\n        pure\n        returns (uint256 dispatchStart, uint256 bodyStart, uint256 bodyEnd)\n    {\n        assembly (\"memory-safe\") {\n            let dispatchLength := and(mload(add(data, 2)), 0xFFFF)\n            dispatchStart := add(data, 0x22)\n            bodyStart := add(dispatchStart, dispatchLength)\n            bodyEnd := add(data, add(0x20, mload(data)))\n        }\n    }\n}\n"
      },
      "lib/rain.solmem/src/lib/LibBytes.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport \"./LibPointer.sol\";\n\n/// Thrown when asked to truncate data to a longer length.\n/// @param length Actual bytes length.\n/// @param truncate Attempted truncation length.\nerror TruncateError(uint256 length, uint256 truncate);\n\n/// @title LibBytes\n/// @notice Tools for working directly with memory in a Solidity compatible way.\nlibrary LibBytes {\n    /// Truncates bytes of data by mutating its length directly.\n    /// Any excess bytes are leaked\n    function truncate(bytes memory data, uint256 length) internal pure {\n        if (data.length < length) {\n            revert TruncateError(data.length, length);\n        }\n        assembly (\"memory-safe\") {\n            mstore(data, length)\n        }\n    }\n\n    /// Pointer to the data of a bytes array NOT the length prefix.\n    /// @param data Bytes to get the data pointer for.\n    /// @return pointer Pointer to the data of the bytes in memory.\n    function dataPointer(bytes memory data) internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(data, 0x20)\n        }\n    }\n\n    /// Pointer to the start of a bytes array (the length prefix).\n    /// @param data Bytes to get the pointer to.\n    /// @return pointer Pointer to the start of the bytes data structure.\n    function startPointer(bytes memory data) internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := data\n        }\n    }\n\n    /// Pointer to the end of some bytes.\n    ///\n    /// Note that this pointer MAY NOT BE ALIGNED, i.e. it MAY NOT point to the\n    /// start of a multiple of 32, UNLIKE the free memory pointer at 0x40.\n    ///\n    /// @param data Bytes to get the pointer to the end of.\n    /// @return pointer Pointer to the end of the bytes data structure.\n    function endDataPointer(bytes memory data) internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(data, add(0x20, mload(data)))\n        }\n    }\n\n    /// Pointer to the end of the memory allocated for bytes.\n    ///\n    /// The allocator is ALWAYS aligned to whole words, i.e. 32 byte multiples,\n    /// for data structures allocated by Solidity. This includes `bytes` which\n    /// means that any time the length of some `bytes` is NOT a multiple of 32\n    /// the alloation will point past the end of the `bytes` data.\n    ///\n    /// There is no guarantee that the memory region between `endDataPointer`\n    /// and `endAllocatedPointer` is zeroed out. It is best to think of that\n    /// space as leaked garbage.\n    ///\n    /// Almost always, e.g. for the purpose of copying data between regions, you\n    /// will want `endDataPointer` rather than this function.\n    /// @param data Bytes to get the end of the allocated data region for.\n    /// @return pointer Pointer to the end of the allocated data region.\n    function endAllocatedPointer(bytes memory data) internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(data, and(add(add(mload(data), 0x20), 0x1f), not(0x1f)))\n        }\n    }\n}\n"
      },
      "lib/rain.solmem/src/lib/LibUint256Array.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"./LibPointer.sol\";\nimport {LibMemCpy} from \"./LibMemCpy.sol\";\nimport {OutOfBoundsTruncate} from \"../error/ErrUint256Array.sol\";\n\n/// @title Uint256Array\n/// @notice Things we want to do carefully and efficiently with uint256 arrays\n/// that Solidity doesn't give us native tools for.\nlibrary LibUint256Array {\n    using LibUint256Array for uint256[];\n\n    /// Pointer to the start (length prefix) of a `uint256[]`.\n    /// @param array The array to get the start pointer of.\n    /// @return pointer The pointer to the start of `array`.\n    function startPointer(uint256[] memory array) internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := array\n        }\n    }\n\n    /// Pointer to the data of a `uint256[]` NOT the length prefix.\n    /// @param array The array to get the data pointer of.\n    /// @return pointer The pointer to the data of `array`.\n    function dataPointer(uint256[] memory array) internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(array, 0x20)\n        }\n    }\n\n    /// Pointer to the end of the allocated memory of an array.\n    /// @param array The array to get the end pointer of.\n    /// @return pointer The pointer to the end of `array`.\n    function endPointer(uint256[] memory array) internal pure returns (Pointer pointer) {\n        assembly (\"memory-safe\") {\n            pointer := add(array, add(0x20, mul(0x20, mload(array))))\n        }\n    }\n\n    /// Cast a `Pointer` to `uint256[]` without modification or safety checks.\n    /// The caller MUST ensure the pointer is to a valid region of memory for\n    /// some `uint256[]`.\n    /// @param pointer The pointer to cast to `uint256[]`.\n    /// @return array The cast `uint256[]`.\n    function unsafeAsUint256Array(Pointer pointer) internal pure returns (uint256[] memory array) {\n        assembly (\"memory-safe\") {\n            array := pointer\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a A single integer to build an array around.\n    /// @return array The newly allocated array including `a` as a single item.\n    function arrayFrom(uint256 a) internal pure returns (uint256[] memory array) {\n        assembly (\"memory-safe\") {\n            array := mload(0x40)\n            mstore(array, 1)\n            mstore(add(array, 0x20), a)\n            mstore(0x40, add(array, 0x40))\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a The first integer to build an array around.\n    /// @param b The second integer to build an array around.\n    /// @return array The newly allocated array including `a` and `b` as the only\n    /// items.\n    function arrayFrom(uint256 a, uint256 b) internal pure returns (uint256[] memory array) {\n        assembly (\"memory-safe\") {\n            array := mload(0x40)\n            mstore(array, 2)\n            mstore(add(array, 0x20), a)\n            mstore(add(array, 0x40), b)\n            mstore(0x40, add(array, 0x60))\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a The first integer to build an array around.\n    /// @param b The second integer to build an array around.\n    /// @param c The third integer to build an array around.\n    /// @return array The newly allocated array including `a`, `b` and `c` as the\n    /// only items.\n    function arrayFrom(uint256 a, uint256 b, uint256 c) internal pure returns (uint256[] memory array) {\n        assembly (\"memory-safe\") {\n            array := mload(0x40)\n            mstore(array, 3)\n            mstore(add(array, 0x20), a)\n            mstore(add(array, 0x40), b)\n            mstore(add(array, 0x60), c)\n            mstore(0x40, add(array, 0x80))\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a The first integer to build an array around.\n    /// @param b The second integer to build an array around.\n    /// @param c The third integer to build an array around.\n    /// @param d The fourth integer to build an array around.\n    /// @return array The newly allocated array including `a`, `b`, `c` and `d` as the\n    /// only items.\n    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d) internal pure returns (uint256[] memory array) {\n        assembly (\"memory-safe\") {\n            array := mload(0x40)\n            mstore(array, 4)\n            mstore(add(array, 0x20), a)\n            mstore(add(array, 0x40), b)\n            mstore(add(array, 0x60), c)\n            mstore(add(array, 0x80), d)\n            mstore(0x40, add(array, 0xA0))\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a The first integer to build an array around.\n    /// @param b The second integer to build an array around.\n    /// @param c The third integer to build an array around.\n    /// @param d The fourth integer to build an array around.\n    /// @param e The fifth integer to build an array around.\n    /// @return array The newly allocated array including `a`, `b`, `c`, `d` and\n    /// `e` as the only items.\n    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d, uint256 e)\n        internal\n        pure\n        returns (uint256[] memory array)\n    {\n        assembly (\"memory-safe\") {\n            array := mload(0x40)\n            mstore(array, 5)\n            mstore(add(array, 0x20), a)\n            mstore(add(array, 0x40), b)\n            mstore(add(array, 0x60), c)\n            mstore(add(array, 0x80), d)\n            mstore(add(array, 0xA0), e)\n            mstore(0x40, add(array, 0xC0))\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a The first integer to build an array around.\n    /// @param b The second integer to build an array around.\n    /// @param c The third integer to build an array around.\n    /// @param d The fourth integer to build an array around.\n    /// @param e The fifth integer to build an array around.\n    /// @param f The sixth integer to build an array around.\n    /// @return array The newly allocated array including `a`, `b`, `c`, `d`, `e`\n    /// and `f` as the only items.\n    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d, uint256 e, uint256 f)\n        internal\n        pure\n        returns (uint256[] memory array)\n    {\n        assembly (\"memory-safe\") {\n            array := mload(0x40)\n            mstore(array, 6)\n            mstore(add(array, 0x20), a)\n            mstore(add(array, 0x40), b)\n            mstore(add(array, 0x60), c)\n            mstore(add(array, 0x80), d)\n            mstore(add(array, 0xA0), e)\n            mstore(add(array, 0xC0), f)\n            mstore(0x40, add(array, 0xE0))\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a The head of the new array.\n    /// @param tail The tail of the new array.\n    /// @return array The new array.\n    function arrayFrom(uint256 a, uint256[] memory tail) internal pure returns (uint256[] memory array) {\n        assembly (\"memory-safe\") {\n            let length := add(mload(tail), 1)\n            let outputCursor := mload(0x40)\n            array := outputCursor\n            let outputEnd := add(outputCursor, add(0x20, mul(length, 0x20)))\n            mstore(0x40, outputEnd)\n\n            mstore(outputCursor, length)\n            mstore(add(outputCursor, 0x20), a)\n\n            for {\n                outputCursor := add(outputCursor, 0x40)\n                let inputCursor := add(tail, 0x20)\n            } lt(outputCursor, outputEnd) {\n                outputCursor := add(outputCursor, 0x20)\n                inputCursor := add(inputCursor, 0x20)\n            } { mstore(outputCursor, mload(inputCursor)) }\n        }\n    }\n\n    /// Building arrays from literal components is a common task that introduces\n    /// boilerplate that is either inefficient or error prone.\n    /// @param a The first item of the new array.\n    /// @param b The second item of the new array.\n    /// @param tail The tail of the new array.\n    /// @return array The new array.\n    function arrayFrom(uint256 a, uint256 b, uint256[] memory tail) internal pure returns (uint256[] memory array) {\n        assembly (\"memory-safe\") {\n            let length := add(mload(tail), 2)\n            let outputCursor := mload(0x40)\n            array := outputCursor\n            let outputEnd := add(outputCursor, add(0x20, mul(length, 0x20)))\n            mstore(0x40, outputEnd)\n\n            mstore(outputCursor, length)\n            mstore(add(outputCursor, 0x20), a)\n            mstore(add(outputCursor, 0x40), b)\n\n            for {\n                outputCursor := add(outputCursor, 0x60)\n                let inputCursor := add(tail, 0x20)\n            } lt(outputCursor, outputEnd) {\n                outputCursor := add(outputCursor, 0x20)\n                inputCursor := add(inputCursor, 0x20)\n            } { mstore(outputCursor, mload(inputCursor)) }\n        }\n    }\n\n    /// Solidity provides no way to change the length of in-memory arrays but\n    /// it also does not deallocate memory ever. It is always safe to shrink an\n    /// array that has already been allocated, with the caveat that the\n    /// truncated items will effectively become inaccessible regions of memory.\n    /// That is to say, we deliberately \"leak\" the truncated items, but that is\n    /// no worse than Solidity's native behaviour of leaking everything always.\n    /// The array is MUTATED in place so there is no return value and there is\n    /// no new allocation or copying of data either.\n    /// @param array The array to truncate.\n    /// @param newLength The new length of the array after truncation.\n    function truncate(uint256[] memory array, uint256 newLength) internal pure {\n        if (newLength > array.length) {\n            revert OutOfBoundsTruncate(array.length, newLength);\n        }\n        assembly (\"memory-safe\") {\n            mstore(array, newLength)\n        }\n    }\n\n    /// Extends `base_` with `extend_` by allocating only an additional\n    /// `extend_.length` words onto `base_` and copying only `extend_` if\n    /// possible. If `base_` is large this MAY be significantly more efficient\n    /// than allocating `base_.length + extend_.length` for an entirely new array\n    /// and copying both `base_` and `extend_` into the new array one item at a\n    /// time in Solidity.\n    ///\n    /// The efficient version of extension is only possible if the free memory\n    /// pointer sits at the end of the base array at the moment of extension. If\n    /// there is allocated memory after the end of base then extension will\n    /// require copying both the base and extend arays to a new region of memory.\n    /// The caller is responsible for optimising code paths to avoid additional\n    /// allocations.\n    ///\n    /// This function is UNSAFE because the base array IS MUTATED DIRECTLY by\n    /// some code paths AND THE FINAL RETURN ARRAY MAY POINT TO THE SAME REGION\n    /// OF MEMORY. It is NOT POSSIBLE to reliably see this behaviour from the\n    /// caller in all cases as the Solidity compiler optimisations may switch the\n    /// caller between the allocating and non-allocating logic due to subtle\n    /// optimisation reasons. To use this function safely THE CALLER MUST NOT USE\n    /// THE BASE ARRAY AND MUST USE THE RETURNED ARRAY ONLY. It is safe to use\n    /// the extend array after calling this function as it is never mutated, it\n    /// is only copied from.\n    ///\n    /// @param b The base integer array that will be extended by `e`.\n    /// @param e The extend integer array that extends `b`.\n    /// @return extended The extended array of `b` extended by `e`.\n    function unsafeExtend(uint256[] memory b, uint256[] memory e) internal pure returns (uint256[] memory extended) {\n        assembly (\"memory-safe\") {\n            // Slither doesn't recognise assembly function names as mixed case\n            // even if they are.\n            // https://github.com/crytic/slither/issues/1815\n            //slither-disable-next-line naming-convention\n            function extendInline(base, extend) -> baseAfter {\n                let outputCursor := mload(0x40)\n                let baseLength := mload(base)\n                let baseEnd := add(base, add(0x20, mul(baseLength, 0x20)))\n\n                // If base is NOT the last thing in allocated memory, allocate,\n                // copy and recurse.\n                switch eq(outputCursor, baseEnd)\n                case 0 {\n                    let newBase := outputCursor\n                    let newBaseEnd := add(newBase, sub(baseEnd, base))\n                    mstore(0x40, newBaseEnd)\n                    for { let inputCursor := base } lt(outputCursor, newBaseEnd) {\n                        inputCursor := add(inputCursor, 0x20)\n                        outputCursor := add(outputCursor, 0x20)\n                    } { mstore(outputCursor, mload(inputCursor)) }\n\n                    baseAfter := extendInline(newBase, extend)\n                }\n                case 1 {\n                    let totalLength_ := add(baseLength, mload(extend))\n                    let outputEnd_ := add(base, add(0x20, mul(totalLength_, 0x20)))\n                    mstore(base, totalLength_)\n                    mstore(0x40, outputEnd_)\n                    for { let inputCursor := add(extend, 0x20) } lt(outputCursor, outputEnd_) {\n                        inputCursor := add(inputCursor, 0x20)\n                        outputCursor := add(outputCursor, 0x20)\n                    } { mstore(outputCursor, mload(inputCursor)) }\n\n                    baseAfter := base\n                }\n            }\n\n            extended := extendInline(b, e)\n        }\n    }\n\n    /// Reverse an array in place. This is a destructive operation that MUTATES\n    /// the array in place. There is no return value.\n    /// @param array The array to reverse.\n    function reverse(uint256[] memory array) internal pure {\n        assembly (\"memory-safe\") {\n            for {\n                let left := add(array, 0x20)\n                // Right points at the last item in the array. Which is the\n                // length number of items from the length.\n                let right := add(array, mul(mload(array), 0x20))\n            } lt(left, right) {\n                left := add(left, 0x20)\n                right := sub(right, 0x20)\n            } {\n                let leftValue := mload(left)\n                mstore(left, mload(right))\n                mstore(right, leftValue)\n            }\n        }\n    }\n}\n"
      },
      "src/lib/parse/LibParseStackTracker.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ParseStackUnderflow} from \"../../error/ErrParse.sol\";\n\ntype ParseStackTracker is uint256;\n\nlibrary LibParseStackTracker {\n    using LibParseStackTracker for ParseStackTracker;\n\n    /// Pushing inputs requires special handling as the inputs need to be tallied\n    /// separately and in addition to the regular stack pushes.\n    function pushInputs(ParseStackTracker tracker, uint256 n) internal pure returns (ParseStackTracker) {\n        unchecked {\n            tracker = tracker.push(n);\n            uint256 inputs = (ParseStackTracker.unwrap(tracker) >> 8) & 0xFF;\n            inputs += n;\n            return ParseStackTracker.wrap((ParseStackTracker.unwrap(tracker) & ~uint256(0xFF00)) | (inputs << 8));\n        }\n    }\n\n    function push(ParseStackTracker tracker, uint256 n) internal pure returns (ParseStackTracker) {\n        unchecked {\n            uint256 current = ParseStackTracker.unwrap(tracker) & 0xFF;\n            uint256 inputs = (ParseStackTracker.unwrap(tracker) >> 8) & 0xFF;\n            uint256 max = ParseStackTracker.unwrap(tracker) >> 0x10;\n            current += n;\n            if (current > max) {\n                max = current;\n            }\n            return ParseStackTracker.wrap(current | (inputs << 8) | (max << 0x10));\n        }\n    }\n\n    function pop(ParseStackTracker tracker, uint256 n) internal pure returns (ParseStackTracker) {\n        unchecked {\n            uint256 current = ParseStackTracker.unwrap(tracker) & 0xFF;\n            if (current < n) {\n                revert ParseStackUnderflow();\n            }\n            return ParseStackTracker.wrap(ParseStackTracker.unwrap(tracker) - n);\n        }\n    }\n}\n"
      },
      "src/error/ErrOpList.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.19;\n\n/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572\ncontract ErrOpList {}\n\n/// Thrown when a dynamic length array is NOT 1 more than a fixed length array.\n/// Should never happen outside a major breaking change to memory layouts.\nerror BadDynamicLength(uint256 dynamicLength, uint256 standardOpsLength);\n"
      },
      "lib/rain.lib.typecast/src/LibConvert.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @title LibConvert\n/// @notice Type conversions that require additional structural changes to\n/// complete safely. These are NOT mere type casts and involve additional\n/// reads and writes to complete, such as recalculating the length of an array.\n/// The convention \"toX\" is adopted from Rust to imply the additional costs and\n/// consumption of the source to produce the target.\nlibrary LibConvert {\n    /// Convert an array of integers to `bytes` data. This requires modifying\n    /// the length in situ as the integer array length is measured in 32 byte\n    /// increments while the length of `bytes` is the literal number of bytes.\n    ///\n    /// It is unsafe for the caller to use `us_` after it has been converted to\n    /// bytes because there is now two pointers to the same mutable data\n    /// structure AND the length prefix for the `uint256[]` version is corrupt.\n    ///\n    /// @param us_ The integer array to convert to `bytes`.\n    /// @return bytes_ The integer array converted to `bytes` data.\n    function unsafeToBytes(uint256[] memory us_) internal pure returns (bytes memory bytes_) {\n        assembly (\"memory-safe\") {\n            bytes_ := us_\n            // Length in bytes is 32x the length in uint256\n            mstore(bytes_, mul(0x20, mload(bytes_)))\n        }\n    }\n\n    /// Truncate `uint256[]` values down to `uint16[]` then pack this to `bytes`\n    /// without padding or length prefix. Unsafe because the starting `uint256`\n    /// values are not checked for overflow due to the truncation. The caller\n    /// MUST ensure that all values fit in `type(uint16).max` or that silent\n    /// overflow is safe.\n    /// @param us_ The `uint256[]` to truncate and concatenate to 16 bit `bytes`.\n    /// @return The concatenated 2-byte chunks.\n    function unsafeTo16BitBytes(uint256[] memory us_) internal pure returns (bytes memory) {\n        unchecked {\n            // We will keep 2 bytes (16 bits) from each integer.\n            bytes memory bytes_ = new bytes(us_.length * 2);\n            assembly (\"memory-safe\") {\n                let replaceMask_ := 0xFFFF\n                let preserveMask_ := not(replaceMask_)\n                for {\n                    let cursor_ := add(us_, 0x20)\n                    let end_ := add(cursor_, mul(mload(us_), 0x20))\n                    let bytesCursor_ := add(bytes_, 0x02)\n                } lt(cursor_, end_) {\n                    cursor_ := add(cursor_, 0x20)\n                    bytesCursor_ := add(bytesCursor_, 0x02)\n                } {\n                    let data_ := mload(bytesCursor_)\n                    mstore(bytesCursor_, or(and(preserveMask_, data_), and(replaceMask_, mload(cursor_))))\n                }\n            }\n            return bytes_;\n        }\n    }\n}\n"
      },
      "src/lib/integrity/LibIntegrityCheckNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.19;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\nimport {\n    StackAllocationMismatch,\n    StackOutputsMismatch,\n    StackUnderflow,\n    StackUnderflowHighwater,\n    BadOpInputsLength,\n    BadOpOutputsLength\n} from \"../../error/ErrIntegrity.sol\";\nimport {IInterpreterV2, SourceIndexV2} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {LibBytecode} from \"rain.interpreter.interface/lib/bytecode/LibBytecode.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {IInterpreterStoreV2, StateNamespace} from \"rain.interpreter.interface/interface/IInterpreterStoreV2.sol\";\nimport {BadOpInputsLength} from \"../../lib/integrity/LibIntegrityCheckNP.sol\";\n\nstruct IntegrityCheckStateNP {\n    uint256 stackIndex;\n    uint256 stackMaxIndex;\n    uint256 readHighwater;\n    uint256[] constants;\n    uint256 opIndex;\n    bytes bytecode;\n}\n\nlibrary LibIntegrityCheckNP {\n    using LibIntegrityCheckNP for IntegrityCheckStateNP;\n\n    function newState(bytes memory bytecode, uint256 stackIndex, uint256[] memory constants)\n        internal\n        pure\n        returns (IntegrityCheckStateNP memory)\n    {\n        return IntegrityCheckStateNP(\n            // stackIndex\n            stackIndex,\n            // stackMaxIndex\n            stackIndex,\n            // highwater (source inputs are always immutable)\n            stackIndex,\n            // constants\n            constants,\n            // opIndex\n            0,\n            // bytecode\n            bytecode\n        );\n    }\n\n    function integrityCheck2(bytes memory fPointers, bytes memory bytecode, uint256[] memory constants)\n        internal\n        view\n        returns (bytes memory io)\n    {\n        unchecked {\n            uint256 sourceCount = LibBytecode.sourceCount(bytecode);\n\n            uint256 fPointersStart;\n            assembly (\"memory-safe\") {\n                fPointersStart := add(fPointers, 0x20)\n            }\n\n            // Ensure that the bytecode has no out of bounds pointers BEFORE we\n            // start attempting to iterate over opcodes. This ensures the\n            // integrity of the source count, relative offset pointers,\n            // ops count per source, and that there is no garbage bytes at the\n            // end or between these things. Basically everything structural about\n            // the bytecode is confirmed here.\n            LibBytecode.checkNoOOBPointers(bytecode);\n\n            io = new bytes(sourceCount * 2);\n            uint256 ioCursor;\n            assembly (\"memory-safe\") {\n                ioCursor := add(io, 0x20)\n            }\n\n            // Run the integrity check over each source. This needs to ensure\n            // the integrity of each source's inputs, outputs, and stack\n            // allocation, as well as the integrity of the bytecode itself on\n            // a per-opcode basis, according to each opcode's implementation.\n            for (uint256 i = 0; i < sourceCount; i++) {\n                (uint256 inputsLength, uint256 outputsLength) = LibBytecode.sourceInputsOutputsLength(bytecode, i);\n                // Inputs and outputs are 1 byte each. This is enforced by the\n                // structure of the bytecode itself.\n                assembly (\"memory-safe\") {\n                    mstore8(ioCursor, inputsLength)\n                    mstore8(add(ioCursor, 1), outputsLength)\n                    ioCursor := add(ioCursor, 2)\n                }\n\n                IntegrityCheckStateNP memory state = LibIntegrityCheckNP.newState(bytecode, inputsLength, constants);\n\n                // Have low 4 bytes of cursor overlap the first op, skipping the\n                // prefix.\n                uint256 cursor = Pointer.unwrap(LibBytecode.sourcePointer(bytecode, i)) - 0x18;\n                uint256 end = cursor + LibBytecode.sourceOpsCount(bytecode, i) * 4;\n\n                while (cursor < end) {\n                    Operand operand;\n                    uint256 bytecodeOpInputs;\n                    uint256 bytecodeOpOutputs;\n                    function(IntegrityCheckStateNP memory, Operand)\n                    view\n                    returns (uint256, uint256) f;\n                    assembly (\"memory-safe\") {\n                        let word := mload(cursor)\n                        f := shr(0xf0, mload(add(fPointersStart, mul(byte(28, word), 2))))\n                        // 3 bytes mask.\n                        operand := and(word, 0xFFFFFF)\n                        let ioByte := byte(29, word)\n                        bytecodeOpInputs := and(ioByte, 0x0F)\n                        bytecodeOpOutputs := shr(4, ioByte)\n                    }\n                    (uint256 calcOpInputs, uint256 calcOpOutputs) = f(state, operand);\n                    if (calcOpInputs != bytecodeOpInputs) {\n                        revert BadOpInputsLength(state.opIndex, calcOpInputs, bytecodeOpInputs);\n                    }\n                    if (calcOpOutputs != bytecodeOpOutputs) {\n                        revert BadOpOutputsLength(state.opIndex, calcOpOutputs, bytecodeOpOutputs);\n                    }\n\n                    if (calcOpInputs > state.stackIndex) {\n                        revert StackUnderflow(state.opIndex, state.stackIndex, calcOpInputs);\n                    }\n                    state.stackIndex -= calcOpInputs;\n\n                    // The stack index can't move below the highwater.\n                    if (state.stackIndex < state.readHighwater) {\n                        revert StackUnderflowHighwater(state.opIndex, state.stackIndex, state.readHighwater);\n                    }\n\n                    // Let's assume that sane opcode implementations don't\n                    // overflow uint256 due to their outputs.\n                    state.stackIndex += calcOpOutputs;\n\n                    // Ensure the max stack index is updated if needed.\n                    if (state.stackIndex > state.stackMaxIndex) {\n                        state.stackMaxIndex = state.stackIndex;\n                    }\n\n                    // If there are multiple outputs the highwater MUST move.\n                    if (calcOpOutputs > 1) {\n                        state.readHighwater = state.stackIndex;\n                    }\n\n                    state.opIndex++;\n                    cursor += 4;\n                }\n\n                // The final stack max index MUST match the bytecode allocation.\n                if (state.stackMaxIndex != LibBytecode.sourceStackAllocation(bytecode, i)) {\n                    revert StackAllocationMismatch(state.stackMaxIndex, LibBytecode.sourceStackAllocation(bytecode, i));\n                }\n\n                // The final stack index MUST match the bytecode source outputs.\n                if (state.stackIndex != outputsLength) {\n                    revert StackOutputsMismatch(state.stackIndex, outputsLength);\n                }\n            }\n        }\n    }\n}\n"
      },
      "src/lib/state/LibInterpreterStateNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {MemoryKV} from \"rain.lib.memkv/lib/LibMemoryKV.sol\";\nimport {\n    FullyQualifiedNamespace, IInterpreterStoreV2\n} from \"rain.interpreter.interface/interface/IInterpreterStoreV2.sol\";\n\naddress constant STACK_TRACER = address(uint160(uint256(keccak256(\"rain.interpreter.stack-tracer.0\"))));\n\nstruct InterpreterStateNP {\n    Pointer[] stackBottoms;\n    uint256[] constants;\n    uint256 sourceIndex;\n    MemoryKV stateKV;\n    FullyQualifiedNamespace namespace;\n    IInterpreterStoreV2 store;\n    uint256[][] context;\n    bytes bytecode;\n    bytes fs;\n}\n\nlibrary LibInterpreterStateNP {\n    function fingerprint(InterpreterStateNP memory state) internal pure returns (bytes32) {\n        return keccak256(abi.encode(state));\n    }\n\n    function stackBottoms(uint256[][] memory stacks) internal pure returns (Pointer[] memory) {\n        Pointer[] memory bottoms = new Pointer[](stacks.length);\n        assembly (\"memory-safe\") {\n            for {\n                let cursor := add(stacks, 0x20)\n                let end := add(cursor, mul(mload(stacks), 0x20))\n                let bottomsCursor := add(bottoms, 0x20)\n            } lt(cursor, end) {\n                cursor := add(cursor, 0x20)\n                bottomsCursor := add(bottomsCursor, 0x20)\n            } {\n                let stack := mload(cursor)\n                let stackBottom := add(stack, mul(0x20, add(mload(stack), 1)))\n                mstore(bottomsCursor, stackBottom)\n            }\n        }\n        return bottoms;\n    }\n\n    /// Does something that a full node can easily track in its traces that isn't\n    /// an event. Specifically, it calls the tracer contract with the memory\n    /// region between `stackTop` and `stackBottom` as an argument. The source\n    /// index is used literally as a 4 byte prefix to the memory region, so that\n    /// it will be interpreted as a function selector by most tooling that is\n    /// expecting ABI encoded data.\n    ///\n    /// The tracer contract doesn't exist, the whole point is that the call will\n    /// be a no-op, but it will be visible in traces and unambiguous as no other\n    /// call will be made to the tracer contract for any reason other than\n    /// tracing stacks.\n    ///\n    /// Note that the trace is a literal memory region, no ABI encoding or other\n    /// processing is done. The structure is 4 bytes of the source index, then\n    /// 32 byte items for each stack item, in order from top to bottom.\n    ///\n    /// There are several reasons we do this instead of emitting an event:\n    /// - It's cheaper. Way cheaper in the case of large stacks. There is a one\n    ///   time 2600 gas cost to warm the tracer, then all subsequent calls are\n    ///   just 100 gas + memory expansion cost. Using an empty contract means\n    ///   there's no execution cost.\n    ///   (vs. e.g. a solidity contract that would at least attempt a dispatch)\n    ///   Meanwhile, emitting an event costs 375 gas plus 8 gas per byte, plus\n    ///   the cost of the memory expansion.\n    ///   Let's say we have 50 stack items spread over 5 calls:\n    ///   - Using the tracer:\n    ///     ( 2600 + 100 * 4 ) + (51 ** 2) / 512 + (3 * 51)\n    ///     = 3000 + 2601 / 665\n    ///     = 3000 + 4 ~= 3000\n    ///   - Using an event (assuming same memory expansion cost):\n    ///     (375 * 5) + (8 * 50 * 32) + 4\n    ///     = 1875 + 12800 + 4\n    ///     = 14679 (nearly 5x the cost!)\n    /// - Events cannot be emitted from view functions, so we would have to\n    ///   either abandon our view eval (security risk) or return every internal\n    ///   stack back to the caller, to have it handle the event emission. This\n    ///   would be both complex and onerous for caller implementations, and make\n    ///   it much harder for tooling/consumers to reliably find all the data, as\n    ///   it would be spread across callers in potentially inconsistent events.\n    function stackTrace(uint256 parentSourceIndex, uint256 sourceIndex, Pointer stackTop, Pointer stackBottom)\n        internal\n        view\n    {\n        address tracer = STACK_TRACER;\n        assembly (\"memory-safe\") {\n            // We are mutating memory in place to avoid allocation, copying, etc.\n            let beforePtr := sub(stackTop, 0x20)\n            // We need to save the value at the pointer before we overwrite it.\n            let before := mload(beforePtr)\n            mstore(beforePtr, or(shl(0x10, parentSourceIndex), sourceIndex))\n            // We don't care about success, we just want to call the tracer.\n            let success := staticcall(gas(), tracer, sub(stackTop, 4), add(sub(stackBottom, stackTop), 4), 0, 0)\n            // Restore the value at the pointer that we mutated above.\n            mstore(beforePtr, before)\n        }\n    }\n}\n"
      },
      "src/lib/op/00/LibOpStackNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\n\n/// Thrown when a stack read index is outside the current stack top.\nerror OutOfBoundsStackRead(uint256 opIndex, uint256 stackTopIndex, uint256 stackRead);\n\n/// @title LibOpStackNP\n/// Implementation of copying a stack item from the stack to the stack.\n/// Integrated deeply into LibParse, which requires this opcode or a variant\n/// to be present at a known opcode index.\nlibrary LibOpStackNP {\n    function integrity(IntegrityCheckStateNP memory state, Operand operand) internal pure returns (uint256, uint256) {\n        uint256 readIndex = Operand.unwrap(operand) & 0xFFFF;\n        // Operand is the index so ensure it doesn't exceed the stack index.\n        if (readIndex >= state.stackIndex) {\n            revert OutOfBoundsStackRead(state.opIndex, state.stackIndex, readIndex);\n        }\n\n        // Move the read highwater if needed.\n        if (readIndex > state.readHighwater) {\n            state.readHighwater = readIndex;\n        }\n\n        return (0, 1);\n    }\n\n    function run(InterpreterStateNP memory state, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 sourceIndex = state.sourceIndex;\n        assembly (\"memory-safe\") {\n            let stackBottom := mload(add(mload(state), mul(0x20, add(sourceIndex, 1))))\n            let stackValue := mload(sub(stackBottom, mul(0x20, add(and(operand, 0xFFFF), 1))))\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, stackValue)\n        }\n        return stackTop;\n    }\n}\n"
      },
      "src/lib/op/00/LibOpConstantNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// Thrown when a constant read index is outside the constants array.\nerror OutOfBoundsConstantRead(uint256 opIndex, uint256 constantsLength, uint256 constantRead);\n\n/// @title LibOpConstantNP\n/// Implementation of copying a constant from the constants array to the stack.\n/// Integrated deeply into LibParse, which requires this opcode or a variant\n/// to be present at a known opcode index.\nlibrary LibOpConstantNP {\n    function integrity(IntegrityCheckStateNP memory state, Operand operand) internal pure returns (uint256, uint256) {\n        // Operand is the index so ensure it doesn't exceed the constants length.\n        uint256 constantIndex = Operand.unwrap(operand) & 0xFFFF;\n        if (constantIndex >= state.constants.length) {\n            revert OutOfBoundsConstantRead(state.opIndex, state.constants.length, constantIndex);\n        }\n        // As inputs MUST always be 0, we don't have to check the high byte of\n        // the operand here, the integrity check will do that for us.\n        return (0, 1);\n    }\n\n    function run(InterpreterStateNP memory state, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256[] memory constants = state.constants;\n        // Skip index OOB check and rely on integrity check for that.\n        assembly (\"memory-safe\") {\n            let value := mload(add(constants, mul(add(and(operand, 0xFFFF), 1), 0x20)))\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, value)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory state, Operand operand, uint256[] memory)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        uint256 index = Operand.unwrap(operand) & 0xFFFF;\n        outputs = new uint256[](1);\n        outputs[0] = state.constants[index];\n    }\n}\n"
      },
      "src/lib/op/00/LibOpExternNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {NotAnExternContract} from \"../../../error/ErrExtern.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {\n    IInterpreterExternV3,\n    ExternDispatch,\n    EncodedExternDispatch\n} from \"rain.interpreter.interface/interface/IInterpreterExternV3.sol\";\nimport {LibExtern} from \"../../extern/LibExtern.sol\";\nimport {LibMemCpy} from \"rain.solmem/lib/LibMemCpy.sol\";\nimport {LibUint256Array} from \"rain.solmem/lib/LibUint256Array.sol\";\nimport {ERC165Checker} from \"openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\";\n\n/// Thrown when a constant read index is outside the constants array.\nerror OutOfBoundsConstantRead(uint256 opIndex, uint256 constantsLength, uint256 constantRead);\n\n/// Thrown when the outputs length is not equal to the expected length.\nerror BadOutputsLength(uint256 expectedLength, uint256 actualLength);\n\n/// @title LibOpExternNP\n/// @notice Implementation of calling an external contract.\nlibrary LibOpExternNP {\n    using LibUint256Array for uint256[];\n\n    function integrity(IntegrityCheckStateNP memory state, Operand operand) internal view returns (uint256, uint256) {\n        uint256 encodedExternDispatchIndex = Operand.unwrap(operand) & 0xFFFF;\n\n        EncodedExternDispatch encodedExternDispatch =\n            EncodedExternDispatch.wrap(state.constants[encodedExternDispatchIndex]);\n        (IInterpreterExternV3 extern, ExternDispatch dispatch) = LibExtern.decodeExternCall(encodedExternDispatch);\n        if (!ERC165Checker.supportsInterface(address(extern), type(IInterpreterExternV3).interfaceId)) {\n            revert NotAnExternContract(address(extern));\n        }\n        uint256 expectedInputsLength = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        uint256 expectedOutputsLength = (Operand.unwrap(operand) >> 0x14) & 0x0F;\n        //slither-disable-next-line unused-return\n        return extern.externIntegrity(dispatch, expectedInputsLength, expectedOutputsLength);\n    }\n\n    function run(InterpreterStateNP memory state, Operand operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 encodedExternDispatchIndex = Operand.unwrap(operand) & 0xFFFF;\n        uint256 inputsLength = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        uint256 outputsLength = (Operand.unwrap(operand) >> 0x14) & 0x0F;\n\n        uint256 encodedExternDispatch = state.constants[encodedExternDispatchIndex];\n        (IInterpreterExternV3 extern, ExternDispatch dispatch) =\n            LibExtern.decodeExternCall(EncodedExternDispatch.wrap(encodedExternDispatch));\n        uint256[] memory inputs;\n        uint256 head;\n        assembly (\"memory-safe\") {\n            // Mutate the word before the current stack top to be the length of\n            // the inputs array so we can treat it as an inputs array. This will\n            // either mutate memory allocated to the stack that is not currently\n            // in use, or the length of the stack array itself, which will need\n            // to be repaired after the call. We store the original value of the\n            // word before the stack top so we can restore it after the call,\n            // just in case it is the latter scenario.\n            inputs := sub(stackTop, 0x20)\n            head := mload(inputs)\n            mstore(inputs, inputsLength)\n        }\n        uint256[] memory outputs = extern.extern(dispatch, inputs);\n        if (outputsLength != outputs.length) {\n            revert BadOutputsLength(outputsLength, outputs.length);\n        }\n\n        assembly (\"memory-safe\") {\n            // Restore whatever was in memory before we built our inputs array.\n            // Inputs is no longer safe to use after this point.\n            mstore(inputs, head)\n            stackTop := add(stackTop, mul(inputsLength, 0x20))\n            // Copy outputs out.\n            let sourceCursor := add(outputs, 0x20)\n            let end := add(sourceCursor, mul(outputsLength, 0x20))\n            // We loop this backwards so that the 0th output is _lowest_ on the\n            // stack, which visually maps to:\n            // `a b: extern<x 2>(a b);`\n            // If the extern implementation is an identity function and has both\n            // inputs and outputs as `[a, b]`.\n            for {} lt(sourceCursor, end) { sourceCursor := add(sourceCursor, 0x20) } {\n                stackTop := sub(stackTop, 0x20)\n                mstore(stackTop, mload(sourceCursor))\n            }\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory state, Operand operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory outputs)\n    {\n        uint256 encodedExternDispatchIndex = Operand.unwrap(operand) & 0xFFFF;\n        uint256 outputsLength = (Operand.unwrap(operand) >> 0x14) & 0x0F;\n\n        uint256 encodedExternDispatch = state.constants[encodedExternDispatchIndex];\n        (IInterpreterExternV3 extern, ExternDispatch dispatch) =\n            LibExtern.decodeExternCall(EncodedExternDispatch.wrap(encodedExternDispatch));\n        outputs = extern.extern(dispatch, inputs);\n        if (outputs.length != outputsLength) {\n            revert BadOutputsLength(outputsLength, outputs.length);\n        }\n        // The stack is built backwards, so we need to reverse the outputs.\n        LibUint256Array.reverse(outputs);\n    }\n}\n"
      },
      "src/lib/op/bitwise/LibOpBitwiseAndNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpBitwiseAndNP\n/// @notice Opcode for computing bitwise AND from the top two items on the stack.\nlibrary LibOpBitwiseAndNP {\n    /// The operand does nothing. Always 2 inputs and 1 output.\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 2 inputs and 1 output.\n        return (2, 1);\n    }\n\n    /// Bitwise AND the top two items on the stack.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        Pointer stackTopAfter;\n        assembly (\"memory-safe\") {\n            stackTopAfter := add(stackTop, 0x20)\n            mstore(stackTopAfter, and(mload(stackTop), mload(stackTopAfter)))\n        }\n        return stackTopAfter;\n    }\n\n    /// Reference implementation for bitwise AND.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = inputs[0] & inputs[1];\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/bitwise/LibOpBitwiseOrNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpBitwiseOrNP\n/// @notice Opcode for computing bitwise OR from the top two items on the stack.\nlibrary LibOpBitwiseOrNP {\n    /// The operand does nothing. Always 2 inputs and 1 output.\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 2 inputs and 1 output.\n        return (2, 1);\n    }\n\n    /// Bitwise OR the top two items on the stack.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        Pointer stackTopAfter;\n        assembly (\"memory-safe\") {\n            stackTopAfter := add(stackTop, 0x20)\n            mstore(stackTopAfter, or(mload(stackTop), mload(stackTopAfter)))\n        }\n        return stackTopAfter;\n    }\n\n    /// Reference implementation for bitwise OR.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = inputs[0] | inputs[1];\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/bitwise/LibOpCtPopNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {LibCtPop} from \"../../bitwise/LibCtPop.sol\";\n\n/// @title LibOpCtPopNP\n/// @notice An opcode that counts the number of bits set in a word. This is\n/// called ctpop because that's the name of this kind of thing elsewhere, but\n/// the more common name is \"population count\" or \"Hamming weight\". The word\n/// in the standard ops lib is called `bitwise-count-ones`, which follows the\n/// Rust naming convention.\n/// There is no evm opcode for this, so we have to implement it ourselves.\nlibrary LibOpCtPopNP {\n    /// ctpop unconditionally takes one value and returns one value.\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (1, 1);\n    }\n\n    /// Output is the number of bits set to one in the input. Thin wrapper around\n    /// `LibCtPop.ctpop`.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 value;\n        assembly (\"memory-safe\") {\n            value := mload(stackTop)\n        }\n        value = LibCtPop.ctpop(value);\n        assembly (\"memory-safe\") {\n            mstore(stackTop, value)\n        }\n        return stackTop;\n    }\n\n    /// The reference implementation of ctpop.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        inputs[0] = LibCtPop.ctpopSlow(inputs[0]);\n        return inputs;\n    }\n}\n"
      },
      "src/lib/op/bitwise/LibOpDecodeBitsNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {LibOpEncodeBitsNP} from \"./LibOpEncodeBitsNP.sol\";\n\n/// @title LibOpDecodeBitsNP\n/// @notice Opcode for decoding binary data from a 256 bit value that was encoded\n/// with LibOpEncodeBitsNP.\nlibrary LibOpDecodeBitsNP {\n    /// Decode takes a single value and returns the decoded value.\n    function integrity(IntegrityCheckStateNP memory state, Operand operand) internal pure returns (uint256, uint256) {\n        // Use exact same integrity check as encode other than the return values.\n        // All we're interested in is the errors that might be thrown.\n        //slither-disable-next-line unused-return\n        LibOpEncodeBitsNP.integrity(state, operand);\n\n        return (1, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        unchecked {\n            uint256 value;\n            assembly (\"memory-safe\") {\n                value := mload(stackTop)\n            }\n\n            // We decode as a start and length of bits. This avoids mistakes such as\n            // inclusive/exclusive ranges, and makes it easier to reason about the\n            // encoding.\n            uint256 startBit = Operand.unwrap(operand) & 0xFF;\n            uint256 length = (Operand.unwrap(operand) >> 8) & 0xFF;\n\n            // Build a bitmask of desired length. Max length is uint8 max which\n            // is 255. A 256 length doesn't really make sense as that isn't an\n            // encoding anyway, it's just the value verbatim.\n            //slither-disable-next-line incorrect-shift\n            uint256 mask = (1 << length) - 1;\n            value = (value >> startBit) & mask;\n\n            assembly (\"memory-safe\") {\n                mstore(stackTop, value)\n            }\n            return stackTop;\n        }\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // We decode as a start and length of bits. This avoids mistakes such as\n        // inclusive/exclusive ranges, and makes it easier to reason about the\n        // encoding.\n        uint256 startBit = Operand.unwrap(operand) & 0xFF;\n        uint256 length = (Operand.unwrap(operand) >> 8) & 0xFF;\n\n        // Build a bitmask of desired length. Max length is uint8 max which\n        // is 255. A 256 length doesn't really make sense as that isn't an\n        // encoding anyway, it's just the value verbatim.\n        uint256 mask = (2 ** length) - 1;\n        outputs = new uint256[](1);\n        outputs[0] = (inputs[0] >> startBit) & mask;\n    }\n}\n"
      },
      "src/lib/op/bitwise/LibOpEncodeBitsNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ZeroLengthBitwiseEncoding, TruncatedBitwiseEncoding} from \"../../../error/ErrBitwise.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpEncodeBitsNP\n/// @notice Opcode for encoding binary data into a 256 bit value.\nlibrary LibOpEncodeBitsNP {\n    /// Encode takes two values and returns one value. The first value is the\n    /// source, the second value is the target.\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        uint256 startBit = Operand.unwrap(operand) & 0xFF;\n        uint256 length = (Operand.unwrap(operand) >> 8) & 0xFF;\n\n        if (length == 0) {\n            revert ZeroLengthBitwiseEncoding();\n        }\n        if (startBit + length > 256) {\n            revert TruncatedBitwiseEncoding(startBit, length);\n        }\n        return (2, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        unchecked {\n            uint256 source;\n            uint256 target;\n            assembly (\"memory-safe\") {\n                source := mload(stackTop)\n                stackTop := add(stackTop, 0x20)\n                target := mload(stackTop)\n            }\n\n            // We encode as a start and length of bits. This avoids mistakes such as\n            // inclusive/exclusive ranges, and makes it easier to reason about the\n            // encoding.\n            uint256 startBit = Operand.unwrap(operand) & 0xFF;\n            uint256 length = (Operand.unwrap(operand) >> 8) & 0xFF;\n\n            // Build a bitmask of desired length. Max length is uint8 max which\n            // is 255. A 256 length doesn't really make sense as that isn't an\n            // encoding anyway, it's just the source verbatim.\n            uint256 mask = (2 ** length - 1);\n\n            // Punch a mask sized hole in target.\n            target &= ~(mask << startBit);\n\n            // Fill the hole with masked bytes from source.\n            target |= (source & mask) << startBit;\n\n            assembly (\"memory-safe\") {\n                mstore(stackTop, target)\n            }\n            return stackTop;\n        }\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        uint256 source = inputs[0];\n        uint256 target = inputs[1];\n\n        // We encode as a start and length of bits. This avoids mistakes such as\n        // inclusive/exclusive ranges, and makes it easier to reason about the\n        // encoding.\n        uint256 startBit = Operand.unwrap(operand) & 0xFF;\n        uint256 length = (Operand.unwrap(operand) >> 8) & 0xFF;\n\n        // Build a bitmask of desired length. Max length is uint8 max which\n        // is 255. A 256 length doesn't really make sense as that isn't an\n        // encoding anyway, it's just the source verbatim.\n        uint256 mask = (2 ** length - 1);\n\n        // Punch a mask sized hole in target.\n        target &= ~(mask << startBit);\n\n        // Fill the hole with masked bytes from source.\n        target |= (source & mask) << startBit;\n\n        outputs = new uint256[](1);\n        outputs[0] = target;\n    }\n}\n"
      },
      "src/lib/op/bitwise/LibOpShiftBitsLeftNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {UnsupportedBitwiseShiftAmount} from \"../../../error/ErrBitwise.sol\";\n\n/// @title LibOpShiftBitsLeftNP\n/// @notice Opcode for shifting bits left. The shift amount is taken from the\n/// operand so it is compile time constant.\nlibrary LibOpShiftBitsLeftNP {\n    /// Shift bits left by the amount specified in the operand.\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        uint256 shiftAmount = Operand.unwrap(operand) & 0xFFFF;\n\n        if (\n            // Shift amount must not result in the output always being 0.\n            shiftAmount > uint256(type(uint8).max)\n            // Shift amount must not result in a noop.\n            || shiftAmount == 0\n        ) {\n            revert UnsupportedBitwiseShiftAmount(shiftAmount);\n        }\n\n        // Always 1 input and 1 output.\n        return (1, 1);\n    }\n\n    /// Shift bits left by the amount specified in the operand.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            mstore(stackTop, shl(and(operand, 0xFF), mload(stackTop)))\n        }\n        return stackTop;\n    }\n\n    /// Reference implementation for shifting bits left.\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256 shiftAmount = Operand.unwrap(operand) & 0xFFFF;\n        inputs[0] = inputs[0] << shiftAmount;\n        return inputs;\n    }\n}\n"
      },
      "src/lib/op/bitwise/LibOpShiftBitsRightNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {UnsupportedBitwiseShiftAmount} from \"../../../error/ErrBitwise.sol\";\n\n/// @title LibOpShiftBitsRightNP\n/// @notice Opcode for shifting bits right. The shift amount is taken from the\n/// operand so it is compile time constant.\nlibrary LibOpShiftBitsRightNP {\n    /// Shift bits right by the amount specified in the operand.\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        uint256 shiftAmount = Operand.unwrap(operand) & 0xFFFF;\n\n        if (\n            // Shift amount must not result in the output always being 0.\n            shiftAmount > type(uint8).max\n            // Shift amount must not result in a noop.\n            || shiftAmount == 0\n        ) {\n            revert UnsupportedBitwiseShiftAmount(shiftAmount);\n        }\n\n        // Always 1 input and 1 output.\n        return (1, 1);\n    }\n\n    /// Shift bits right by the amount specified in the operand.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            mstore(stackTop, shr(and(operand, 0xFF), mload(stackTop)))\n        }\n        return stackTop;\n    }\n\n    /// Reference implementation for shifting bits right.\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256 shiftAmount = Operand.unwrap(operand) & 0xFFFF;\n        inputs[0] = inputs[0] >> shiftAmount;\n        return inputs;\n    }\n}\n"
      },
      "src/lib/op/call/LibOpCallNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {LibInterpreterStateNP, InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {LibIntegrityCheckNP, IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Pointer, LibPointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {LibBytecode} from \"rain.interpreter.interface/lib/bytecode/LibBytecode.sol\";\nimport {LibEvalNP} from \"../../eval/LibEvalNP.sol\";\n\n/// Thrown when the outputs requested by the operand exceed the outputs\n/// available from the source.\n/// @param sourceOutputs The number of outputs available from the source.\n/// @param outputs The number of outputs requested by the operand.\nerror CallOutputsExceedSource(uint256 sourceOutputs, uint256 outputs);\n\n/// @title LibOpCallNP\n/// @notice Contains the call operation. This allows sources to be treated in a\n/// function-like manner. Primarily intended as a way for expression authors to\n/// create reusable logic inline with their expression, in a way that mimics how\n/// words and stack consumption works at the Solidity level.\n///\n/// Similarities between `call` and a traditional function:\n/// - The source is called with a set of 0+ inputs.\n/// - The source returns a set of 0+ outputs.\n/// - The source has a fixed number of inputs and outputs.\n/// - When the source executes it has its own stack/scope.\n/// - Sources use lexical scoping rules for named LHS items.\n/// - The source can be called from multiple places.\n/// - The source can `call` other sources.\n/// - The source is stateless across calls\n///   (although it can use words like get/set to read/write external state).\n/// - The caller and callee have to agree on the number of inputs\n///   (but not outputs, see below).\n/// - Generally speaking, the behaviour of a source can be reasoned about\n///   without needing to know the context in which it is called. Which is the\n///   basic requirement for reusability.\n///\n/// Differences between `call` and a traditional function:\n/// - The caller defines the number of outputs to be returned, NOT the callee.\n///   This is because the caller is responsible for allocating space on the\n///   stack for the outputs, and the callee is responsible for providing the\n///   outputs. The only limitation is that the caller cannot request more\n///   outputs than the callee has available. This means that two calls to the\n///   same source can return different numbers of outputs in different contexts.\n/// - The inputs to a source are considered to be the top of the callee's stack\n///   from the perspective of the caller. This means that the inputs are eligible\n///   to be read as outputs, if the caller chooses to do so.\n/// - The sources are not named, they are identified by their index in the\n///   bytecode. Tooling can provide sugar over this but the underlying\n///   representation is just an index.\n/// - Sources are not \"first class\" like functions often are, i.e. they cannot\n///   be passed as arguments to other sources or otherwise be treated as values.\n/// - Recursion is not supported. This is because currently there is no laziness\n///   in the interpreter, so a recursive call would result in an infinite loop\n///   unconditionally (even when wrapped in an `if`). This may change in the\n///   future.\n/// - The memory allocation for a source must be known at compile time.\n/// - There's no way to return early from a source.\n///\n/// The order of inputs and outputs is designed so that the visual representation\n/// of a source call matches the visual representation of a function call. This\n/// requires some reversals of order \"under the hood\" while copying data around\n/// but it makes the behaviour of `call` more intuitive.\n///\n/// Illustrative example:\n/// ```\n/// /* Final result */\n/// /* a = 2 */\n/// /* b = 9 */\n/// a b: call<1 2>(10 5); ten five:, a b: int-div(ten five) 9;\n/// ```\nlibrary LibOpCallNP {\n    using LibPointer for Pointer;\n\n    function integrity(IntegrityCheckStateNP memory state, Operand operand) internal pure returns (uint256, uint256) {\n        uint256 sourceIndex = Operand.unwrap(operand) & 0xFFFF;\n        uint256 outputs = Operand.unwrap(operand) >> 0x14;\n\n        (uint256 sourceInputs, uint256 sourceOutputs) =\n            LibBytecode.sourceInputsOutputsLength(state.bytecode, sourceIndex);\n\n        if (sourceOutputs < outputs) {\n            revert CallOutputsExceedSource(sourceOutputs, outputs);\n        }\n\n        return (sourceInputs, outputs);\n    }\n\n    /// The `call` word is conceptually very simple. It takes a source index, a\n    /// number of outputs, and a number of inputs. It then runs the standard\n    /// eval loop for the source, with a starting stack pointer above the inputs,\n    /// and then copies the outputs to the calling stack.\n    function run(InterpreterStateNP memory state, Operand operand, Pointer stackTop) internal view returns (Pointer) {\n        // Extract config from the operand.\n        uint256 sourceIndex = Operand.unwrap(operand) & 0xFFFF;\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        uint256 outputs = Operand.unwrap(operand) >> 0x14;\n\n        // Copy inputs in. The inputs have to be copied in reverse order so that\n        // the top of the stack from the perspective of `call`, i.e. the first\n        // input to call, is the bottom of the stack from the perspective of the\n        // callee.\n        Pointer[] memory stackBottoms = state.stackBottoms;\n        Pointer evalStackBottom;\n        Pointer evalStackTop;\n        assembly (\"memory-safe\") {\n            evalStackBottom := mload(add(stackBottoms, mul(add(sourceIndex, 1), 0x20)))\n            evalStackTop := evalStackBottom\n            let end := add(stackTop, mul(inputs, 0x20))\n            for {} lt(stackTop, end) { stackTop := add(stackTop, 0x20) } {\n                evalStackTop := sub(evalStackTop, 0x20)\n                mstore(evalStackTop, mload(stackTop))\n            }\n        }\n\n        // Keep a copy of the current source index so that we can restore it\n        // after the call.\n        uint256 currentSourceIndex = state.sourceIndex;\n\n        // Set the state to the source we are calling.\n        state.sourceIndex = sourceIndex;\n\n        // Run the eval loop.\n        evalStackTop = LibEvalNP.evalLoopNP(state, currentSourceIndex, evalStackTop, evalStackBottom);\n\n        // Restore the source index in the state.\n        state.sourceIndex = currentSourceIndex;\n\n        // Copy outputs out.\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, mul(outputs, 0x20))\n            let end := add(evalStackTop, mul(outputs, 0x20))\n            let cursor := stackTop\n            for {} lt(evalStackTop, end) {\n                cursor := add(cursor, 0x20)\n                evalStackTop := add(evalStackTop, 0x20)\n            } { mstore(cursor, mload(evalStackTop)) }\n        }\n\n        return stackTop;\n    }\n}\n"
      },
      "src/lib/op/context/LibOpContextNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\nlibrary LibOpContextNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Context doesn't have any inputs. The operand defines the reads.\n        // Unfortunately we don't know the shape of the context that we will\n        // receive at runtime, so we can't check the reads at integrity time.\n        return (0, 1);\n    }\n\n    function run(InterpreterStateNP memory state, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 i = Operand.unwrap(operand) & 0xFF;\n        uint256 j = (Operand.unwrap(operand) >> 8) & 0xFF;\n        // We want these indexes to be checked at runtime for OOB accesses\n        // because we don't know the shape of the context at compile time.\n        // Solidity handles that for us as long as we don't invoke yul for the\n        // reads.\n        if (Pointer.unwrap(stackTop) < 0x20) {\n            revert(\"stack underflow\");\n        }\n        uint256 v = state.context[i][j];\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, v)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory state, Operand operand, uint256[] memory)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        uint256 i = Operand.unwrap(operand) & 0xFF;\n        uint256 j = (Operand.unwrap(operand) >> 8) & 0xFF;\n        // We want these indexes to be checked at runtime for OOB accesses\n        // because we don't know the shape of the context at compile time.\n        // Solidity handles that for us as long as we don't invoke yul for the\n        // reads.\n        uint256 v = state.context[i][j];\n        outputs = new uint256[](1);\n        outputs[0] = v;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/crypto/LibOpHashNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpHashNP\n/// Implementation of keccak256 hashing as a standard Rainlang opcode.\nlibrary LibOpHashNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // Any number of inputs are valid.\n        // 0 inputs will be the hash of empty (0 length) bytes.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        return (inputs, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let length := mul(and(shr(0x10, operand), 0x0F), 0x20)\n            let value := keccak256(stackTop, length)\n            stackTop := sub(add(stackTop, length), 0x20)\n            mstore(stackTop, value)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = uint256(keccak256(abi.encodePacked(inputs)));\n    }\n}\n"
      },
      "src/lib/op/erc20/LibOpERC20AllowanceNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IERC20} from \"openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title OpERC20AllowanceNP\n/// @notice Opcode for getting the current erc20 allowance of an account.\nlibrary LibOpERC20AllowanceNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 3 inputs, the token, the owner and the spender.\n        // Always 1 output, the allowance.\n        return (3, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 token;\n        uint256 owner;\n        uint256 spender;\n        assembly (\"memory-safe\") {\n            token := mload(stackTop)\n            owner := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n            spender := mload(stackTop)\n        }\n        uint256 tokenAllowance =\n            IERC20(address(uint160(token))).allowance(address(uint160(owner)), address(uint160(spender)));\n        assembly (\"memory-safe\") {\n            mstore(stackTop, tokenAllowance)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256 token = inputs[0];\n        uint256 owner = inputs[1];\n        uint256 spender = inputs[2];\n        uint256 tokenAllowance =\n            IERC20(address(uint160(token))).allowance(address(uint160(owner)), address(uint160(spender)));\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = tokenAllowance;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/erc20/LibOpERC20BalanceOfNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IERC20} from \"openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title OpERC20BalanceOfNP\n/// @notice Opcode for getting the current erc20 balance of an account.\nlibrary LibOpERC20BalanceOfNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 2 inputs, the token and the account.\n        // Always 1 output, the balance.\n        return (2, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 token;\n        uint256 account;\n        assembly (\"memory-safe\") {\n            token := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            account := mload(stackTop)\n        }\n        uint256 tokenBalance = IERC20(address(uint160(token))).balanceOf(address(uint160(account)));\n        assembly (\"memory-safe\") {\n            mstore(stackTop, tokenBalance)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256 token = inputs[0];\n        uint256 account = inputs[1];\n        uint256 tokenBalance = IERC20(address(uint160(token))).balanceOf(address(uint160(account)));\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = tokenBalance;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/erc20/LibOpERC20TotalSupplyNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {IERC20} from \"openzeppelin-contracts/contracts/interfaces/IERC20.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpERC20TotalSupplyNP\n/// @notice Opcode for ERC20 `totalSupply`.\nlibrary LibOpERC20TotalSupplyNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 1 input, the contract.\n        // Always 1 output, the total supply.\n        return (1, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 account;\n        assembly {\n            account := mload(stackTop)\n        }\n        uint256 totalSupply = IERC20(address(uint160(account))).totalSupply();\n        assembly {\n            mstore(stackTop, totalSupply)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256 account = inputs[0];\n        uint256 totalSupply = IERC20(address(uint160(account))).totalSupply();\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = totalSupply;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/erc721/LibOpERC721BalanceOfNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IERC721} from \"openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title OpERC721BalanceOfNP\n/// @notice Opcode for getting the current erc721 balance of an account.\nlibrary LibOpERC721BalanceOfNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 2 inputs, the token and the account.\n        // Always 1 output, the balance.\n        return (2, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 token;\n        uint256 account;\n        assembly (\"memory-safe\") {\n            token := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            account := mload(stackTop)\n        }\n        uint256 tokenBalance = IERC721(address(uint160(token))).balanceOf(address(uint160(account)));\n        assembly (\"memory-safe\") {\n            mstore(stackTop, tokenBalance)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256 token = inputs[0];\n        uint256 account = inputs[1];\n        uint256 tokenBalance = IERC721(address(uint160(token))).balanceOf(address(uint160(account)));\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = tokenBalance;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/erc721/LibOpERC721OwnerOfNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IERC721} from \"openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpERC721OwnerOfNP\n/// @notice Opcode for getting the current owner of an erc721 token.\nlibrary LibOpERC721OwnerOfNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 2 inputs, the token and the tokenId.\n        // Always 1 output, the owner.\n        return (2, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 token;\n        uint256 tokenId;\n        assembly (\"memory-safe\") {\n            token := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            tokenId := mload(stackTop)\n        }\n        address tokenOwner = IERC721(address(uint160(token))).ownerOf(tokenId);\n        assembly (\"memory-safe\") {\n            mstore(stackTop, tokenOwner)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256 token = inputs[0];\n        uint256 tokenId = inputs[1];\n        address tokenOwner = IERC721(address(uint160(token))).ownerOf(tokenId);\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = uint256(uint160(tokenOwner));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/erc5313/LibOpERC5313OwnerNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {IERC5313} from \"openzeppelin-contracts/contracts/interfaces/IERC5313.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpERC5313OwnerNP\n/// @notice Opcode for ERC5313 `owner`.\nlibrary LibOpERC5313OwnerNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 1 input, the contract.\n        // Always 1 output, the owner.\n        return (1, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 account;\n        assembly {\n            account := mload(stackTop)\n        }\n        address owner = IERC5313(address(uint160(account))).owner();\n        assembly {\n            mstore(stackTop, owner)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256 account = inputs[0];\n        address owner = IERC5313(address(uint160(account))).owner();\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = uint256(uint160(owner));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/evm/LibOpBlockNumberNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpBlockNumberNP\n/// Implementation of the EVM `BLOCKNUMBER` opcode as a standard Rainlang opcode.\nlibrary LibOpBlockNumberNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (0, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, number())\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = block.number;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/evm/LibOpChainIdNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpChainIdNP\n/// Implementation of the EVM `CHAINID` opcode as a standard Rainlang opcode.\nlibrary LibOpChainIdNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (0, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, chainid())\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = block.chainid;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/evm/LibOpMaxUint256NP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpMaxUint256NP\n/// Exposes `type(uint256).max` as a Rainlang opcode.\nlibrary LibOpMaxUint256NP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (0, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 value = type(uint256).max;\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, value)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = type(uint256).max;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/evm/LibOpTimestampNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP, LibInterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpTimestampNP\n/// Implementation of the EVM `TIMESTAMP` opcode as a standard Rainlang opcode.\nlibrary LibOpTimestampNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (0, 1);\n    }\n\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal view returns (Pointer) {\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, timestamp())\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = block.timestamp;\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpAnyNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpAnyNP\n/// @notice Opcode to return the first nonzero item on the stack up to the inputs\n/// limit.\nlibrary LibOpAnyNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least one input.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 0 ? inputs : 1;\n        return (inputs, 1);\n    }\n\n    /// ANY\n    /// ANY is the first nonzero item, else 0.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let length := mul(and(shr(0x10, operand), 0x0F), 0x20)\n            let cursor := stackTop\n            stackTop := sub(add(stackTop, length), 0x20)\n            for { let end := add(cursor, length) } lt(cursor, end) { cursor := add(cursor, 0x20) } {\n                let item := mload(cursor)\n                if gt(item, 0) {\n                    mstore(stackTop, item)\n                    break\n                }\n            }\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of ANY for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Zero length inputs is not supported so this 0 will always be written\n        // over.\n        uint256 value = 0;\n        for (uint256 i = 0; i < inputs.length; i++) {\n            value = inputs[i];\n            if (value != 0) {\n                break;\n            }\n        }\n        outputs = new uint256[](1);\n        outputs[0] = value;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpConditionsNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {LibIntOrAString, IntOrAString} from \"rain.intorastring/src/lib/LibIntOrAString.sol\";\n\n/// @title LibOpConditionsNP\n/// @notice Opcode to return the first nonzero item on the stack up to the inputs\n/// limit.\nlibrary LibOpConditionsNP {\n    using LibIntOrAString for IntOrAString;\n\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 2 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// `conditions`\n    /// Pairwise list of conditions and values. The first nonzero condition\n    /// evaluated puts its corresponding value on the stack. `conditions` is\n    /// eagerly evaluated. If no condition is nonzero, the expression will\n    /// revert. The number of inputs must be even. The number of outputs is 1.\n    /// If an author wants to provide some default value, they can set the last\n    /// condition to some nonzero constant value such as 1.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 condition;\n        IntOrAString reason = IntOrAString.wrap(0);\n        assembly (\"memory-safe\") {\n            let inputs := and(shr(0x10, operand), 0x0F)\n            let oddInputs := mod(inputs, 2)\n\n            let cursor := stackTop\n            for {\n                let end := add(cursor, mul(sub(inputs, oddInputs), 0x20))\n                stackTop := sub(end, mul(iszero(oddInputs), 0x20))\n                if oddInputs { reason := mload(end) }\n            } lt(cursor, end) { cursor := add(cursor, 0x40) } {\n                condition := mload(cursor)\n                if condition {\n                    mstore(stackTop, mload(add(cursor, 0x20)))\n                    break\n                }\n            }\n        }\n        require(condition > 0, reason.toString());\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of `condition` for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that any overflow errors come from the real\n        // implementation.\n        unchecked {\n            uint256 length = inputs.length;\n            outputs = new uint256[](1);\n            for (uint256 i = 0; i < length; i += 2) {\n                if (inputs[i] != 0) {\n                    outputs[0] = inputs[i + 1];\n                    return outputs;\n                }\n            }\n            if (inputs.length % 2 != 0) {\n                IntOrAString reason = IntOrAString.wrap(inputs[length - 1]);\n                require(false, reason.toString());\n            } else {\n                require(false, \"\");\n            }\n        }\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpEnsureNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {LibIntOrAString, IntOrAString} from \"rain.intorastring/src/lib/LibIntOrAString.sol\";\n\n/// @title LibOpEnsureNP\n/// @notice Opcode to revert if the condition is zero.\nlibrary LibOpEnsureNP {\n    using LibIntOrAString for IntOrAString;\n\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be exactly 2 inputs.\n        return (2, 0);\n    }\n\n    /// `ensure`\n    /// If the condition is zero, the expression will revert with the given\n    /// string.\n    /// All conditions are eagerly evaluated and there are no outputs.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 condition;\n        IntOrAString reason;\n        assembly (\"memory-safe\") {\n            condition := mload(stackTop)\n            reason := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n\n        require(condition > 0, reason.toString());\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of `ensure` for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        require(inputs[0] > 0, IntOrAString.wrap(inputs[1]).toString());\n        outputs = new uint256[](0);\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpEqualToNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpEqualToNP\n/// @notice Opcode to return 1 if the first item on the stack is equal to\n/// the second item on the stack, else 0.\nlibrary LibOpEqualToNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (2, 1);\n    }\n\n    /// EQ\n    /// EQ is 1 if the first item is equal to the second item, else 0.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            mstore(stackTop, eq(a, mload(stackTop)))\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of EQ for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0] == inputs[1] ? 1 : 0;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpEveryNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpEveryNP\n/// @notice Opcode to return the last item out of N items if they are all true,\n/// else 0.\nlibrary LibOpEveryNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least one input.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 0 ? inputs : 1;\n        return (inputs, 1);\n    }\n\n    /// EVERY is the last nonzero item, else 0.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let length := mul(and(shr(0x10, operand), 0x0F), 0x20)\n            let cursor := stackTop\n            stackTop := sub(add(stackTop, length), 0x20)\n            for { let end := add(cursor, length) } lt(cursor, end) { cursor := add(cursor, 0x20) } {\n                let item := mload(cursor)\n                if iszero(item) {\n                    mstore(stackTop, item)\n                    break\n                }\n            }\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of EVERY for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Zero length inputs is not supported so this 0 will always be written\n        // over.\n        uint256 value = 0;\n        for (uint256 i = 0; i < inputs.length; i++) {\n            value = inputs[i];\n            if (value == 0) {\n                break;\n            }\n        }\n        outputs = new uint256[](1);\n        outputs[0] = value;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpGreaterThanNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpGreaterThanNP\n/// @notice Opcode to return 1 if the first item on the stack is greater than\n/// the second item on the stack, else 0.\nlibrary LibOpGreaterThanNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (2, 1);\n    }\n\n    /// GT\n    /// GT is 1 if the first item is greater than the second item, else 0.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            mstore(stackTop, gt(a, mload(stackTop)))\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of GT for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0] > inputs[1] ? 1 : 0;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpGreaterThanOrEqualToNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpGreaterThanOrEqualToNP\n/// @notice Opcode to return 1 if the first item on the stack is greater than or\n/// equal to the second item on the stack, else 0.\nlibrary LibOpGreaterThanOrEqualToNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (2, 1);\n    }\n\n    /// GTE\n    /// GTE is 1 if the first item is greater than or equal to the second item,\n    /// else 0.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            mstore(stackTop, iszero(lt(a, mload(stackTop))))\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of GTE for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0] >= inputs[1] ? 1 : 0;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpIfNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpIfNP\n/// @notice Opcode to choose between two values based on a condition. If is\n/// eager, meaning both values are evaluated before the condition is checked.\nlibrary LibOpIfNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (3, 1);\n    }\n\n    /// IF\n    /// IF is a conditional. If the first item on the stack is nonero, the second\n    /// item is returned, else the third item is returned.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let condition := mload(stackTop)\n            stackTop := add(stackTop, 0x40)\n            mstore(stackTop, mload(sub(stackTop, mul(0x20, iszero(iszero(condition))))))\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of IF for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0] > 0 ? inputs[1] : inputs[2];\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpIsZeroNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpIsZeroNP\n/// @notice Opcode to return 1 if the top item on the stack is zero, else 0.\nlibrary LibOpIsZeroNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (1, 1);\n    }\n\n    /// ISZERO\n    /// ISZERO is 1 if the top item is zero, else 0.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            mstore(stackTop, iszero(mload(stackTop)))\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of ISZERO for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0] == 0 ? 1 : 0;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpLessThanNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpLessThanNP\n/// @notice Opcode to return 1 if the first item on the stack is less than\n/// the second item on the stack, else 0.\nlibrary LibOpLessThanNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (2, 1);\n    }\n\n    /// LT\n    /// LT is 1 if the first item is less than the second item, else 0.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            mstore(stackTop, lt(a, mload(stackTop)))\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of LT for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0] < inputs[1] ? 1 : 0;\n    }\n}\n"
      },
      "src/lib/op/logic/LibOpLessThanOrEqualToNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpLessThanOrEqualToNP\n/// @notice Opcode to return 1 if the first item on the stack is less than or\n/// equal to the second item on the stack, else 0.\nlibrary LibOpLessThanOrEqualToNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (2, 1);\n    }\n\n    /// LTE\n    /// LTE is 1 if the first item is less than or equal to the second item,\n    /// else 0.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            let a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            mstore(stackTop, iszero(gt(a, mload(stackTop))))\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of LTE for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0] <= inputs[1] ? 1 : 0;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/growth/LibOpDecimal18ExponentialGrowthNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, mul, pow} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18ExponentialGrowthNP\n/// @notice Exponential growth is base(1 + rate)^t where base is the initial\n/// value, rate is the growth rate, and t is time.\nlibrary LibOpDecimal18ExponentialGrowthNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be three inputs and one output.\n        return (3, 1);\n    }\n\n    /// decimal18-exponential-growth\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 base;\n        uint256 rate;\n        uint256 t;\n        assembly (\"memory-safe\") {\n            base := mload(stackTop)\n            rate := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n            t := mload(stackTop)\n        }\n        base = UD60x18.unwrap(mul(UD60x18.wrap(base), pow(UD60x18.wrap(1e18 + rate), UD60x18.wrap(t))));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, base)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] =\n            UD60x18.unwrap(mul(UD60x18.wrap(inputs[0]), pow(UD60x18.wrap(1e18 + inputs[1]), UD60x18.wrap(inputs[2]))));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/growth/LibOpDecimal18LinearGrowthNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, mul, add} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18LinearGrowthNP\n/// @notice Linear growth is base + rate * t where a is the initial value, r is\n/// the growth rate, and t is time.\nlibrary LibOpDecimal18LinearGrowthNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be three inputs and one output.\n        return (3, 1);\n    }\n\n    /// decimal18-linear-growth\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 base;\n        uint256 rate;\n        uint256 t;\n        assembly (\"memory-safe\") {\n            base := mload(stackTop)\n            rate := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n            t := mload(stackTop)\n        }\n        base = UD60x18.unwrap(add(UD60x18.wrap(base), mul(UD60x18.wrap(rate), UD60x18.wrap(t))));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, base)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(add(UD60x18.wrap(inputs[0]), mul(UD60x18.wrap(inputs[1]), UD60x18.wrap(inputs[2]))));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18AvgNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, avg} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18AvgNP\n/// @notice Opcode for the average of two decimal 18 fixed point numbers.\nlibrary LibOpDecimal18AvgNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be two inputs and one output.\n        return (2, 1);\n    }\n\n    /// decimal18-avg\n    /// 18 decimal fixed point average of two numbers.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            b := mload(stackTop)\n        }\n        a = UD60x18.unwrap(avg(UD60x18.wrap(a), UD60x18.wrap(b)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of avg for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(avg(UD60x18.wrap(inputs[0]), UD60x18.wrap(inputs[1])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18CeilNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, ceil} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18CeilNP\n/// @notice Opcode for the ceiling of an decimal 18 fixed point number.\nlibrary LibOpDecimal18CeilNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-ceil\n    /// 18 decimal fixed point ceiling of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(ceil(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of ceil for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(ceil(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18MulNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// Used for reference implementation so that we have two independent\n/// upstreams to compare against.\nimport {Math as OZMath} from \"openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport {UD60x18, mul} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {LibWillOverflow} from \"rain.math.fixedpoint/lib/LibWillOverflow.sol\";\n\n/// @title LibOpDecimal18MulNP\n/// @notice Opcode to mul N 18 decimal fixed point values. Errors on overflow.\nlibrary LibOpDecimal18MulNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// decimal18-mul\n    /// 18 decimal fixed point multiplication with implied overflow checks from\n    /// PRB Math.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        a = UD60x18.unwrap(mul(UD60x18.wrap(a), UD60x18.wrap(b)));\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a = UD60x18.unwrap(mul(UD60x18.wrap(a), UD60x18.wrap(b)));\n                unchecked {\n                    i++;\n                }\n            }\n        }\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of multiplication for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 a = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                uint256 b = inputs[i];\n                if (LibWillOverflow.mulDivWillOverflow(a, b, 1e18)) {\n                    a = uint256(keccak256(abi.encodePacked(\"overflow sentinel\")));\n                    break;\n                }\n                a = OZMath.mulDiv(a, b, 1e18);\n            }\n            outputs = new uint256[](1);\n            outputs[0] = a;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18DivNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// Used for reference implementation so that we have two independent\n/// upstreams to compare against.\nimport {Math as OZMath} from \"openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport {LibWillOverflow} from \"rain.math.fixedpoint/lib/LibWillOverflow.sol\";\nimport {UD60x18, div} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18DivNP\n/// @notice Opcode to div N 18 decimal fixed point values. Errors on overflow.\nlibrary LibOpDecimal18DivNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// decimal18-div\n    /// 18 decimal fixed point division with implied overflow checks from PRB\n    /// Math.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        a = UD60x18.unwrap(div(UD60x18.wrap(a), UD60x18.wrap(b)));\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a = UD60x18.unwrap(div(UD60x18.wrap(a), UD60x18.wrap(b)));\n                unchecked {\n                    i++;\n                }\n            }\n        }\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of division for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 a = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                uint256 b = inputs[i];\n                // Just bail out with a = some sentinel value if we're going to\n                // overflow or divide by zero. This gives the real implementation\n                // space to throw its own error that the test harness is expecting.\n                // We don't want the real implementation to fail to throw the\n                // error and also produce the same result, so a needs to have\n                // some collision resistant value.\n                if (b == 0 || LibWillOverflow.mulDivWillOverflow(a, 1e18, b)) {\n                    a = uint256(keccak256(abi.encodePacked(\"overflow sentinel\")));\n                    break;\n                }\n                a = OZMath.mulDiv(a, 1e18, b);\n            }\n            outputs = new uint256[](1);\n            outputs[0] = a;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18ExpNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, exp} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18ExpNP\n/// @notice Opcode for the natural exponential e^x as decimal 18 fixed point.\nlibrary LibOpDecimal18ExpNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-exp\n    /// 18 decimal fixed point natural exponent of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(exp(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of exp for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(exp(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18Exp2NP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, exp2} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18Exp2NP\n/// @notice Opcode for the binary exponential 2^x as decimal 18 fixed point.\nlibrary LibOpDecimal18Exp2NP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-exp2\n    /// 18 decimal fixed point binary exponent of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(exp2(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of exp for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(exp2(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18FloorNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, floor} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18FloorNP\n/// @notice Opcode for the floor of an decimal 18 fixed point number.\nlibrary LibOpDecimal18FloorNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one input and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-floor\n    /// 18 decimal fixed point floor of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(floor(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of floor for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(floor(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18FracNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, frac} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18FracNP\n/// @notice Opcode for the frac of an decimal 18 fixed point number.\nlibrary LibOpDecimal18FracNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one input and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-frac\n    /// 18 decimal fixed point frac of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(frac(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of frac for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(frac(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18GmNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, gm} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18GmNP\n/// @notice Opcode for the geometric average of two decimal 18 fixed point\n/// numbers.\nlibrary LibOpDecimal18GmNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be two inputs and one output.\n        return (2, 1);\n    }\n\n    /// decimal18-gm\n    /// 18 decimal fixed point geometric average of two numbers.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            b := mload(stackTop)\n        }\n        a = UD60x18.unwrap(gm(UD60x18.wrap(a), UD60x18.wrap(b)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of gm for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(gm(UD60x18.wrap(inputs[0]), UD60x18.wrap(inputs[1])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18HeadroomNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, frac} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18HeadroomNP\n/// @notice Opcode for the headroom (distance to ceil) of an decimal 18 fixed\n/// point number.\nlibrary LibOpDecimal18HeadroomNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one input and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-headroom\n    /// 18 decimal fixed point headroom of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        // Can't underflow as frac is always less than 1e18.\n        unchecked {\n            a = 1e18 - UD60x18.unwrap(frac(UD60x18.wrap(a)));\n        }\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of headroom for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = 1e18 - UD60x18.unwrap(frac(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18InvNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, inv} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18InvNP\n/// @notice Opcode for the inverse 1 / x of an decimal 18 fixed point number.\nlibrary LibOpDecimal18InvNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-inv\n    /// 18 decimal fixed point inverse of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(inv(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of inv for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(inv(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18LnNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, ln} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18LnNP\n/// @notice Opcode for the natural logarithm of an decimal 18 fixed point number.\nlibrary LibOpDecimal18LnNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-ln\n    /// 18 decimal fixed point natural logarithm of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(ln(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of ln for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(ln(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18Log10NP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, log10} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18Log10NP\n/// @notice Opcode for the common logarithm of an decimal 18 fixed point number.\nlibrary LibOpDecimal18Log10NP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-log10\n    /// 18 decimal fixed point common logarithm of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(log10(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of log10 for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(log10(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18Log2NP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, log2} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18Log2NP\n/// @notice Opcode for the binary logarithm of an decimal 18 fixed point number.\nlibrary LibOpDecimal18Log2NP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-log2\n    /// 18 decimal fixed point binary logarithm of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(log2(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of log2 for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(log2(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18PowNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, pow} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18PowNP\n/// @notice Opcode to pow N 18 decimal fixed point values to an 18 decimal power.\nlibrary LibOpDecimal18PowNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be two inputs and one output.\n        return (2, 1);\n    }\n\n    /// decimal18-pow\n    /// 18 decimal fixed point exponentiation with implied overflow checks from\n    /// PRB Math.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            b := mload(stackTop)\n        }\n        a = UD60x18.unwrap(pow(UD60x18.wrap(a), UD60x18.wrap(b)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of pow for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(pow(UD60x18.wrap(inputs[0]), UD60x18.wrap(inputs[1])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18PowUNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, powu} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18PowUNP\n/// @notice Opcode to pow N 18 decimal fixed point values to a uint256 power.\nlibrary LibOpDecimal18PowUNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be two inputs and one output.\n        return (2, 1);\n    }\n\n    /// decimal18-pow-u\n    /// 18 decimal fixed point exponentiation with implied overflow checks from\n    /// PRB Math.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            b := mload(stackTop)\n        }\n        a = UD60x18.unwrap(powu(UD60x18.wrap(a), b));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of powu for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(powu(UD60x18.wrap(inputs[0]), inputs[1]));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18Scale18DynamicNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibFixedPointDecimalScale} from \"rain.math.fixedpoint/lib/LibFixedPointDecimalScale.sol\";\nimport {MASK_2BIT} from \"sol.lib.binmaskflag/Binary.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpDecimal18Scale18DynamicNP\n/// @notice Opcode for scaling a number to 18 decimal fixed point based on\n/// runtime scale input.\nlibrary LibOpDecimal18Scale18DynamicNP {\n    using LibFixedPointDecimalScale for uint256;\n\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (2, 1);\n    }\n\n    /// decimal18-scale-18-dynamic\n    /// 18 decimal fixed point scaling from runtime value.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 scale;\n        assembly (\"memory-safe\") {\n            scale := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            a := mload(stackTop)\n        }\n        a = a.scale18(scale, Operand.unwrap(operand));\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[1].scale18(inputs[0], Operand.unwrap(operand) & MASK_2BIT);\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18Scale18NP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibFixedPointDecimalScale} from \"rain.math.fixedpoint/lib/LibFixedPointDecimalScale.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpDecimal18Scale18NP\n/// @notice Opcode for scaling a number to 18 decimal fixed point.\nlibrary LibOpDecimal18Scale18NP {\n    using LibFixedPointDecimalScale for uint256;\n\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (1, 1);\n    }\n\n    /// decimal18-scale-18\n    /// 18 decimal fixed point scaling.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = a.scale18(Operand.unwrap(operand) & 0xFF, Operand.unwrap(operand) >> 8);\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0].scale18(Operand.unwrap(operand) & 0xFF, Operand.unwrap(operand) >> 8);\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18ScaleNDynamicNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {LibFixedPointDecimalScale} from \"rain.math.fixedpoint/lib/LibFixedPointDecimalScale.sol\";\nimport {MASK_2BIT} from \"sol.lib.binmaskflag/Binary.sol\";\n\n/// @title LibOpDecimal18ScaleNDynamicNP\n/// @notice Opcode for scaling a number from 18 decimal fixed point based on\n/// runtime scale input.\nlibrary LibOpDecimal18ScaleNDynamicNP {\n    using LibFixedPointDecimalScale for uint256;\n\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (2, 1);\n    }\n\n    /// decimal18-scaleN-dynamic\n    /// 18 decimal fixed point scaling from runtime value.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 scale;\n        assembly (\"memory-safe\") {\n            scale := mload(stackTop)\n            stackTop := add(stackTop, 0x20)\n            a := mload(stackTop)\n        }\n        a = a.scaleN(scale, Operand.unwrap(operand) & MASK_2BIT);\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[1].scaleN(inputs[0], Operand.unwrap(operand) & MASK_2BIT);\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18ScaleNNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibFixedPointDecimalScale} from \"rain.math.fixedpoint/lib/LibFixedPointDecimalScale.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpDecimal18ScaleNNP\n/// @notice Opcode for scaling a decimal18 number to some other scale N.\nlibrary LibOpDecimal18ScaleNNP {\n    using LibFixedPointDecimalScale for uint256;\n\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        return (1, 1);\n    }\n\n    /// decimal18-scale-n\n    /// Scale from 18 decimal to n decimal.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = a.scaleN(Operand.unwrap(operand) & 0xFF, Operand.unwrap(operand) >> 8);\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        outputs = new uint256[](1);\n        outputs[0] = inputs[0].scaleN(Operand.unwrap(operand) & 0xFF, Operand.unwrap(operand) >> 8);\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18SnapToUnitNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {UD60x18, frac, ceil, floor} from \"prb-math/UD60x18.sol\";\n\n/// @title LibOpDecimal18SnapToUnitNP\n/// @notice Opcode for the snap to unit of an decimal 18 fixed point number.\nlibrary LibOpDecimal18SnapToUnitNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be two inputs and one output.\n        return (2, 1);\n    }\n\n    /// decimal18-snap-to-unit\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        unchecked {\n            uint256 threshold;\n            uint256 value;\n            assembly (\"memory-safe\") {\n                threshold := mload(stackTop)\n                stackTop := add(stackTop, 0x20)\n                value := mload(stackTop)\n            }\n            uint256 valueFrac = UD60x18.unwrap(frac(UD60x18.wrap(value)));\n            if (valueFrac <= threshold) {\n                value = UD60x18.unwrap(floor(UD60x18.wrap(value)));\n                assembly (\"memory-safe\") {\n                    mstore(stackTop, value)\n                }\n            }\n            // Frac cannot be more than 1e18, so we can safely subtract it from 1e18\n            // as unchecked.\n            else if ((1e18 - valueFrac) <= threshold) {\n                value = UD60x18.unwrap(ceil(UD60x18.wrap(value)));\n                assembly (\"memory-safe\") {\n                    mstore(stackTop, value)\n                }\n            }\n            return stackTop;\n        }\n    }\n\n    /// Gas intensive reference implementation of snap-to-unit for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        uint256 threshold = inputs[0];\n        uint256 value = inputs[1];\n        uint256 valueFrac = UD60x18.unwrap(frac(UD60x18.wrap(value)));\n        if (valueFrac <= threshold) {\n            value = UD60x18.unwrap(floor(UD60x18.wrap(value)));\n            outputs[0] = value;\n        } else if ((1e18 - valueFrac) <= threshold) {\n            value = UD60x18.unwrap(ceil(UD60x18.wrap(value)));\n            outputs[0] = value;\n        } else {\n            outputs[0] = value;\n        }\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/decimal18/LibOpDecimal18SqrtNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {UD60x18, sqrt} from \"prb-math/UD60x18.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpDecimal18SqrtNP\n/// @notice Opcode for the square root of an decimal 18 fixed point number.\nlibrary LibOpDecimal18SqrtNP {\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // There must be one inputs and one output.\n        return (1, 1);\n    }\n\n    /// decimal18-sqrt\n    /// 18 decimal fixed point square root of a number.\n    function run(InterpreterStateNP memory, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n        }\n        a = UD60x18.unwrap(sqrt(UD60x18.wrap(a)));\n\n        assembly (\"memory-safe\") {\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of sqrt for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256[] memory outputs = new uint256[](1);\n        outputs[0] = UD60x18.unwrap(sqrt(UD60x18.wrap(inputs[0])));\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntAddNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpIntAddNP\n/// @notice Opcode to add N integers. Errors on overflow.\nlibrary LibOpIntAddNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// int-add\n    /// Addition with implied overflow checks from the Solidity 0.8.x compiler.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        a += b;\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a += b;\n                unchecked {\n                    i++;\n                }\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of addition for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc += inputs[i];\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntDivNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpIntDivNP\n/// @notice Opcode to divide N integers. Errors on divide by zero. Truncates\n/// towards zero.\nlibrary LibOpIntDivNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// int-div\n    /// Division with implied checks from the Solidity 0.8.x compiler.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        a /= b;\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a /= b;\n                unchecked {\n                    i++;\n                }\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of division for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc /= inputs[i];\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntExpNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpIntExpNP\n/// @notice Opcode to raise x successively to N integers. Errors on overflow.\nlibrary LibOpIntExpNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// int-exp\n    /// Exponentiation with implied overflow checks from the Solidity 0.8.x\n    /// compiler.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        a = a ** b;\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a = a ** b;\n                unchecked {\n                    i++;\n                }\n            }\n        }\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of exponentiation for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc = acc ** inputs[i];\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntMaxNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpIntMaxNP\n/// @notice Opcode to find the max from N integers.\nlibrary LibOpIntMaxNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// int-max\n    /// Finds the maximum value from N integers.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        if (a < b) {\n            a = b;\n        }\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                if (a < b) {\n                    a = b;\n                }\n                unchecked {\n                    i++;\n                }\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of maximum for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc = acc < inputs[i] ? inputs[i] : acc;\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntMinNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpIntMinNP\n/// @notice Opcode to find the min from N integers.\nlibrary LibOpIntMinNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// int-min\n    /// Finds the minimum value from N integers.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        if (a > b) {\n            a = b;\n        }\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                if (a > b) {\n                    a = b;\n                }\n                unchecked {\n                    i++;\n                }\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of minimum for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc = acc > inputs[i] ? inputs[i] : acc;\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntModNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer, LibPointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpIntModNP\n/// @notice Opcode to modulo N integers. Errors on modulo by zero.\nlibrary LibOpIntModNP {\n    using LibPointer for Pointer;\n\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// int-mod\n    /// Modulo with implied checks from the Solidity 0.8.x compiler.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        a %= b;\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a %= b;\n                unchecked {\n                    i++;\n                }\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of modulo for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc %= inputs[i];\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntMulNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\n\n/// @title LibOpIntMulNP\n/// @notice Opcode to mul N integers. Errors on overflow.\nlibrary LibOpIntMulNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    /// int-mul\n    /// Multiplication with implied overflow checks from the Solidity 0.8.x\n    /// compiler.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n        }\n        a *= b;\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a *= b;\n                unchecked {\n                    i++;\n                }\n            }\n        }\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of multiplication for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc *= inputs[i];\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/math/int/LibOpIntSubNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {IntegrityCheckStateNP} from \"../../../integrity/LibIntegrityCheckNP.sol\";\nimport {InterpreterStateNP} from \"../../../state/LibInterpreterStateNP.sol\";\nimport {SaturatingMath} from \"rain.math.saturating/SaturatingMath.sol\";\n\n/// @title LibOpIntSubNP\n/// @notice Opcode to subtract N integers.\nlibrary LibOpIntSubNP {\n    function integrity(IntegrityCheckStateNP memory, Operand operand) internal pure returns (uint256, uint256) {\n        // There must be at least two inputs.\n        uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n        inputs = inputs > 1 ? inputs : 2;\n        return (inputs, 1);\n    }\n\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a - b;\n    }\n\n    /// int-sub\n    /// Subtraction with implied overflow checks from the Solidity 0.8.x compiler.\n    function run(InterpreterStateNP memory, Operand operand, Pointer stackTop) internal pure returns (Pointer) {\n        uint256 a;\n        uint256 b;\n        uint256 saturate;\n        assembly (\"memory-safe\") {\n            a := mload(stackTop)\n            b := mload(add(stackTop, 0x20))\n            stackTop := add(stackTop, 0x40)\n            saturate := and(operand, 1)\n        }\n        function (uint256, uint256) internal pure returns (uint256) f =\n            saturate > 0 ? SaturatingMath.saturatingSub : sub;\n        a = f(a, b);\n\n        {\n            uint256 inputs = (Operand.unwrap(operand) >> 0x10) & 0x0F;\n            uint256 i = 2;\n            while (i < inputs) {\n                assembly (\"memory-safe\") {\n                    b := mload(stackTop)\n                    stackTop := add(stackTop, 0x20)\n                }\n                a = f(a, b);\n                unchecked {\n                    i++;\n                }\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            stackTop := sub(stackTop, 0x20)\n            mstore(stackTop, a)\n        }\n        return stackTop;\n    }\n\n    /// Gas intensive reference implementation of subtraction for testing.\n    function referenceFn(InterpreterStateNP memory, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory outputs)\n    {\n        // Unchecked so that when we assert that an overflow error is thrown, we\n        // see the revert from the real function and not the reference function.\n        unchecked {\n            uint256 acc = inputs[0];\n            for (uint256 i = 1; i < inputs.length; i++) {\n                acc -= inputs[i];\n            }\n            outputs = new uint256[](1);\n            outputs[0] = acc;\n        }\n    }\n}\n"
      },
      "src/lib/op/store/LibOpGetNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {MemoryKVKey, MemoryKVVal, MemoryKV, LibMemoryKV} from \"rain.lib.memkv/lib/LibMemoryKV.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\n\n/// @title LibOpGetNP\n/// @notice Opcode for reading from storage.\nlibrary LibOpGetNP {\n    using LibMemoryKV for MemoryKV;\n\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 1 input. The key. `hash()` is recommended to build compound\n        // keys.\n        return (1, 1);\n    }\n\n    /// Implements runtime behaviour of the `get` opcode. Attempts to lookup the\n    /// key in the memory key/value store then falls back to the interpreter's\n    /// storage interface as an external call. If the key is not found in either,\n    /// the value will fallback to `0` as per default Solidity/EVM behaviour.\n    /// @param state The interpreter state of the current eval.\n    /// @param stackTop Pointer to the current stack top.\n    function run(InterpreterStateNP memory state, Operand, Pointer stackTop) internal view returns (Pointer) {\n        uint256 key;\n        assembly (\"memory-safe\") {\n            key := mload(stackTop)\n        }\n        (uint256 exists, MemoryKVVal value) = state.stateKV.get(MemoryKVKey.wrap(key));\n\n        // Cache MISS, get from external store.\n        if (exists == 0) {\n            uint256 storeValue = state.store.get(state.namespace, key);\n\n            // Push fetched value to memory to make subsequent lookups on the\n            // same key find a cache HIT.\n            state.stateKV = state.stateKV.set(MemoryKVKey.wrap(key), MemoryKVVal.wrap(storeValue));\n\n            assembly (\"memory-safe\") {\n                mstore(stackTop, storeValue)\n            }\n        }\n        // Cache HIT.\n        else {\n            assembly (\"memory-safe\") {\n                mstore(stackTop, value)\n            }\n        }\n\n        return stackTop;\n    }\n\n    function referenceFn(InterpreterStateNP memory state, Operand, uint256[] memory inputs)\n        internal\n        view\n        returns (uint256[] memory)\n    {\n        uint256 key = inputs[0];\n        (uint256 exists, MemoryKVVal value) = state.stateKV.get(MemoryKVKey.wrap(key));\n        uint256[] memory outputs = new uint256[](1);\n        // Cache MISS, get from external store.\n        if (exists == 0) {\n            uint256 storeValue = state.store.get(state.namespace, key);\n\n            // Push fetched value to memory to make subsequent lookups on the\n            // same key find a cache HIT.\n            state.stateKV = state.stateKV.set(MemoryKVKey.wrap(key), MemoryKVVal.wrap(storeValue));\n\n            outputs[0] = storeValue;\n        }\n        // Cache HIT.\n        else {\n            outputs[0] = MemoryKVVal.unwrap(value);\n        }\n\n        return outputs;\n    }\n}\n"
      },
      "src/lib/op/store/LibOpSetNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {MemoryKV, MemoryKVKey, MemoryKVVal, LibMemoryKV} from \"rain.lib.memkv/lib/LibMemoryKV.sol\";\nimport {IntegrityCheckStateNP} from \"../../integrity/LibIntegrityCheckNP.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {InterpreterStateNP} from \"../../state/LibInterpreterStateNP.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\n\n/// @title LibOpSetNP\n/// @notice Opcode for recording k/v state changes to be set in storage.\nlibrary LibOpSetNP {\n    using LibMemoryKV for MemoryKV;\n\n    function integrity(IntegrityCheckStateNP memory, Operand) internal pure returns (uint256, uint256) {\n        // Always 2 inputs. The key and the value. `hash()` is recommended to\n        // build compound keys.\n        return (2, 0);\n    }\n\n    function run(InterpreterStateNP memory state, Operand, Pointer stackTop) internal pure returns (Pointer) {\n        unchecked {\n            uint256 key;\n            uint256 value;\n            assembly (\"memory-safe\") {\n                key := mload(stackTop)\n                value := mload(add(stackTop, 0x20))\n                stackTop := add(stackTop, 0x40)\n            }\n\n            state.stateKV = state.stateKV.set(MemoryKVKey.wrap(key), MemoryKVVal.wrap(value));\n            return stackTop;\n        }\n    }\n\n    function referenceFn(InterpreterStateNP memory state, Operand, uint256[] memory inputs)\n        internal\n        pure\n        returns (uint256[] memory)\n    {\n        uint256 key = inputs[0];\n        uint256 value = inputs[1];\n        state.stateKV = state.stateKV.set(MemoryKVKey.wrap(key), MemoryKVVal.wrap(value));\n        return new uint256[](0);\n    }\n}\n"
      },
      "src/lib/parse/literal/LibParseLiteralString.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ParseState} from \"../LibParseState.sol\";\nimport {IntOrAString, LibIntOrAString} from \"rain.intorastring/src/lib/LibIntOrAString.sol\";\nimport {UnclosedStringLiteral, StringTooLong} from \"../../../error/ErrParse.sol\";\nimport {CMASK_STRING_LITERAL_END, CMASK_STRING_LITERAL_TAIL} from \"../LibParseCMask.sol\";\nimport {LibParseError} from \"../LibParseError.sol\";\n\n/// @title LibParseLiteralString\n/// @notice A library for parsing string literals.\nlibrary LibParseLiteralString {\n    using LibParseError for ParseState;\n    using LibParseLiteralString for ParseState;\n\n    /// Find the bounds for some string literal at the cursor. The caller is\n    /// responsible for checking that the cursor is at the start of a string\n    /// literal. Bounds are as per `boundLiteral`.\n    function boundString(ParseState memory state, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (uint256, uint256, uint256)\n    {\n        unchecked {\n            uint256 innerStart = cursor + 1;\n            uint256 innerEnd;\n            uint256 outerEnd;\n            {\n                uint256 stringCharMask = CMASK_STRING_LITERAL_TAIL;\n                uint256 stringData;\n                uint256 i = 0;\n                assembly (\"memory-safe\") {\n                    let distanceFromEnd := sub(end, innerStart)\n                    let max := 0x20\n                    if lt(distanceFromEnd, 0x20) { max := distanceFromEnd }\n\n                    // Only up to 31 bytes of string data can be stored in a\n                    // single word, so strings can't be longer than 31 bytes.\n                    // The 32nd byte is the length of the string.\n                    stringData := mload(innerStart)\n                    //slither-disable-next-line incorrect-shift\n                    for {} and(lt(i, max), iszero(iszero(and(shl(byte(i, stringData), 1), stringCharMask)))) {} {\n                        i := add(i, 1)\n                    }\n                }\n                if (i == 0x20) {\n                    revert StringTooLong(state.parseErrorOffset(cursor));\n                }\n                innerEnd = innerStart + i;\n                uint256 finalChar;\n                assembly (\"memory-safe\") {\n                    finalChar := byte(0, mload(innerEnd))\n                }\n\n                // End can't equal inner end, because then we would move past the\n                // end of the data considering the final \" character.\n                //slither-disable-next-line incorrect-shift\n                if (1 << finalChar & CMASK_STRING_LITERAL_END == 0 || end == innerEnd) {\n                    revert UnclosedStringLiteral(state.parseErrorOffset(innerEnd));\n                }\n                // Outer end is after the final `\"`.\n                outerEnd = innerEnd + 1;\n            }\n\n            return (innerStart, innerEnd, outerEnd);\n        }\n    }\n\n    /// Algorithm for parsing string literals:\n    /// - Get the inner length of the string\n    /// - Mutate memory in place to add a length prefix, record the original data\n    /// - Use this solidity string to build an `IntOrAString`\n    /// - Restore the original data that the length prefix overwrote\n    /// - Return the `IntOrAString`\n    function parseString(ParseState memory state, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (uint256, uint256)\n    {\n        uint256 stringStart;\n        uint256 stringEnd;\n        (stringStart, stringEnd, cursor) = state.boundString(cursor, end);\n        IntOrAString intOrAString;\n\n        uint256 memSnapshot;\n        string memory str;\n        assembly (\"memory-safe\") {\n            let length := sub(stringEnd, stringStart)\n            str := sub(stringStart, 0x20)\n            memSnapshot := mload(str)\n            mstore(str, length)\n        }\n        intOrAString = LibIntOrAString.fromString(str);\n        assembly (\"memory-safe\") {\n            mstore(str, memSnapshot)\n        }\n        return (cursor, IntOrAString.unwrap(intOrAString));\n    }\n}\n"
      },
      "src/lib/parse/literal/LibParseLiteralDecimal.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ParseState} from \"../LibParseState.sol\";\nimport {DecimalLiteralOverflow, ZeroLengthDecimal, MalformedExponentDigits} from \"../../../error/ErrParse.sol\";\nimport {CMASK_E_NOTATION, CMASK_NUMERIC_0_9} from \"../LibParseCMask.sol\";\nimport {LibParseError} from \"../LibParseError.sol\";\n\nlibrary LibParseLiteralDecimal {\n    using LibParseError for ParseState;\n    using LibParseLiteralDecimal for ParseState;\n\n    function boundDecimal(ParseState memory state, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (uint256, uint256, uint256)\n    {\n        uint256 innerStart = cursor;\n        uint256 innerEnd = innerStart;\n        uint256 ePosition = 0;\n        uint256 eExists = 0;\n\n        {\n            uint256 decimalCharMask = CMASK_NUMERIC_0_9;\n            uint256 eMask = CMASK_E_NOTATION;\n            assembly (\"memory-safe\") {\n                //slither-disable-next-line incorrect-shift\n                for {} and(iszero(iszero(and(shl(byte(0, mload(innerEnd)), 1), decimalCharMask))), lt(innerEnd, end)) {}\n                {\n                    innerEnd := add(innerEnd, 1)\n                }\n\n                // If we're now pointing at an e notation, then we need\n                // to move past it. Negative exponents are not supported.\n                //slither-disable-next-line incorrect-shift\n                if and(iszero(iszero(and(shl(byte(0, mload(innerEnd)), 1), eMask))), lt(innerEnd, end)) {\n                    ePosition := innerEnd\n                    innerEnd := add(innerEnd, 1)\n                    eExists := 1\n\n                    // Move past the exponent digits.\n                    //slither-disable-next-line incorrect-shift\n                    for {} and(\n                        iszero(iszero(and(shl(byte(0, mload(innerEnd)), 1), decimalCharMask))), lt(innerEnd, end)\n                    ) {} { innerEnd := add(innerEnd, 1) }\n                }\n            }\n        }\n        if (\n            (ePosition != 0 && (innerEnd > ePosition + 3 || innerEnd == ePosition + 1))\n            // if e is found at the start of the literal, with no digits before\n            // it that is malformed.\n            || (ePosition == innerStart && eExists == 1)\n        ) {\n            revert MalformedExponentDigits(state.parseErrorOffset(ePosition));\n        }\n\n        return (innerStart, innerEnd, innerEnd);\n    }\n\n    /// Algorithm for parsing decimal literals:\n    /// - start at the end of the literal\n    /// - for each digit:\n    ///   - multiply the digit by 10^digit position\n    ///   - add the result to the total\n    /// - return the total\n    ///\n    /// This algorithm is ONLY safe if the caller has already checked that the\n    /// start/end span a non-zero length of valid decimal chars. The caller\n    /// can most easily do this by using the `boundLiteral` function.\n    ///\n    /// Unsafe behavior is undefined and can easily result in out of bounds\n    /// reads as there are no checks that start/end are within `data`.\n    function parseDecimal(ParseState memory state, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (uint256, uint256)\n    {\n        unchecked {\n            uint256 value;\n            // The ASCII byte can be translated to a numeric digit by subtracting\n            // the digit offset.\n            uint256 digitOffset = uint256(uint8(bytes1(\"0\")));\n            // Tracks the exponent of the current digit. Can start above 0 if\n            // the literal is in e notation.\n            uint256 exponent;\n            (uint256 decimalStart, uint256 decimalEnd, uint256 outerEnd) = state.boundDecimal(cursor, end);\n            {\n                uint256 word;\n                //slither-disable-next-line similar-names\n                uint256 decimalCharByte;\n                uint256 decimalLength = decimalEnd - decimalStart;\n                assembly (\"memory-safe\") {\n                    word := mload(sub(decimalEnd, 3))\n                    decimalCharByte := byte(0, word)\n                }\n                // If the last 3 bytes are e notation, then we need to parse\n                // the exponent as a 2 digit number.\n                //slither-disable-next-line incorrect-shift\n                if (decimalLength > 3 && ((1 << decimalCharByte) & CMASK_E_NOTATION) != 0) {\n                    cursor = decimalEnd - 4;\n                    assembly (\"memory-safe\") {\n                        exponent := add(sub(byte(2, word), digitOffset), mul(sub(byte(1, word), digitOffset), 10))\n                    }\n                } else {\n                    assembly (\"memory-safe\") {\n                        decimalCharByte := byte(1, word)\n                    }\n                    // If the last 2 bytes are e notation, then we need to parse\n                    // the exponent as a 1 digit number.\n                    //slither-disable-next-line incorrect-shift\n                    if (decimalLength > 2 && ((1 << decimalCharByte) & CMASK_E_NOTATION) != 0) {\n                        cursor = decimalEnd - 3;\n                        assembly (\"memory-safe\") {\n                            exponent := sub(byte(2, word), digitOffset)\n                        }\n                    }\n                    // Otherwise, we're not in e notation and we can start at the\n                    // decimalEnd of the literal with 0 starting exponent.\n                    else if (decimalLength > 0) {\n                        cursor = decimalEnd - 1;\n                        exponent = 0;\n                    } else {\n                        revert ZeroLengthDecimal(state.parseErrorOffset(decimalStart));\n                    }\n                }\n            }\n\n            // Anything under 10^77 is safe to raise to its power of 10 without\n            // overflowing a uint256.\n            while (cursor >= decimalStart && exponent < 77) {\n                // We don't need to check the bounds of the byte because\n                // we know it is a decimal literal as long as the bounds\n                // are correct (calculated in `boundLiteral`).\n                assembly (\"memory-safe\") {\n                    value := add(value, mul(sub(byte(0, mload(cursor)), digitOffset), exp(10, exponent)))\n                }\n                exponent++;\n                cursor--;\n            }\n\n            // If we didn't consume the entire literal, then we have\n            // to check if the remaining digit is safe to multiply\n            // by 10 without overflowing a uint256.\n            if (cursor >= decimalStart) {\n                {\n                    uint256 digit;\n                    assembly (\"memory-safe\") {\n                        digit := sub(byte(0, mload(cursor)), digitOffset)\n                    }\n                    // If the digit is greater than 1, then we know that\n                    // multiplying it by 10^77 will overflow a uint256.\n                    if (digit > 1) {\n                        revert DecimalLiteralOverflow(state.parseErrorOffset(cursor));\n                    } else {\n                        uint256 scaled = digit * (10 ** exponent);\n                        if (value + scaled < value) {\n                            revert DecimalLiteralOverflow(state.parseErrorOffset(cursor));\n                        }\n                        value += scaled;\n                    }\n                    cursor--;\n                }\n\n                {\n                    // If we didn't consume the entire literal, then only\n                    // leading zeros are allowed.\n                    while (cursor >= decimalStart) {\n                        //slither-disable-next-line similar-names\n                        uint256 decimalCharByte;\n                        assembly (\"memory-safe\") {\n                            decimalCharByte := byte(0, mload(cursor))\n                        }\n                        if (decimalCharByte != uint256(uint8(bytes1(\"0\")))) {\n                            revert DecimalLiteralOverflow(state.parseErrorOffset(cursor));\n                        }\n                        cursor--;\n                    }\n                }\n            }\n            return (outerEnd, value);\n        }\n    }\n}\n"
      },
      "src/lib/parse/literal/LibParseLiteralHex.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ParseState} from \"../LibParseState.sol\";\nimport {\n    MalformedHexLiteral,\n    OddLengthHexLiteral,\n    ZeroLengthHexLiteral,\n    HexLiteralOverflow\n} from \"../../../error/ErrParse.sol\";\nimport {CMASK_UPPER_ALPHA_A_F, CMASK_LOWER_ALPHA_A_F, CMASK_NUMERIC_0_9, CMASK_HEX} from \"../LibParseCMask.sol\";\nimport {LibParseError} from \"../LibParseError.sol\";\n\nlibrary LibParseLiteralHex {\n    using LibParseLiteralHex for ParseState;\n    using LibParseError for ParseState;\n\n    function boundHex(ParseState memory, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (uint256, uint256, uint256)\n    {\n        uint256 innerStart = cursor + 2;\n        uint256 innerEnd = innerStart;\n        {\n            uint256 hexCharMask = CMASK_HEX;\n            assembly (\"memory-safe\") {\n                //slither-disable-next-line incorrect-shift\n                for {} and(iszero(iszero(and(shl(byte(0, mload(innerEnd)), 1), hexCharMask))), lt(innerEnd, end)) {} {\n                    innerEnd := add(innerEnd, 1)\n                }\n            }\n        }\n\n        return (innerStart, innerEnd, innerEnd);\n    }\n\n    /// Algorithm for parsing hexadecimal literals:\n    /// - start at the end of the literal\n    /// - for each character:\n    ///   - convert the character to a nybble\n    ///   - shift the nybble into the total at the correct position\n    ///     (4 bits per nybble)\n    /// - return the total\n    function parseHex(ParseState memory state, uint256 cursor, uint256 end) internal pure returns (uint256, uint256) {\n        unchecked {\n            uint256 value;\n            uint256 hexStart;\n            uint256 hexEnd;\n            (hexStart, hexEnd, cursor) = state.boundHex(cursor, end);\n\n            uint256 hexLength = hexEnd - hexStart;\n            if (hexLength > 0x40) {\n                revert HexLiteralOverflow(state.parseErrorOffset(hexStart));\n            } else if (hexLength == 0) {\n                revert ZeroLengthHexLiteral(state.parseErrorOffset(hexStart));\n            } else if (hexLength % 2 == 1) {\n                revert OddLengthHexLiteral(state.parseErrorOffset(hexStart));\n            } else {\n                // Loop the cursor backwards over the hex string, we'll return\n                // the hex end instead.\n                cursor = hexEnd - 1;\n                uint256 valueOffset = 0;\n                while (cursor >= hexStart) {\n                    uint256 hexCharByte;\n                    assembly (\"memory-safe\") {\n                        hexCharByte := byte(0, mload(cursor))\n                    }\n                    //slither-disable-next-line incorrect-shift\n                    uint256 hexChar = 1 << hexCharByte;\n\n                    uint256 nybble;\n                    // 0-9\n                    if (hexChar & CMASK_NUMERIC_0_9 != 0) {\n                        nybble = hexCharByte - uint256(uint8(bytes1(\"0\")));\n                    }\n                    // a-f\n                    else if (hexChar & CMASK_LOWER_ALPHA_A_F != 0) {\n                        nybble = hexCharByte - uint256(uint8(bytes1(\"a\"))) + 10;\n                    }\n                    // A-F\n                    else if (hexChar & CMASK_UPPER_ALPHA_A_F != 0) {\n                        nybble = hexCharByte - uint256(uint8(bytes1(\"A\"))) + 10;\n                    } else {\n                        revert MalformedHexLiteral(state.parseErrorOffset(cursor));\n                    }\n\n                    value |= nybble << valueOffset;\n                    valueOffset += 4;\n                    cursor--;\n                }\n            }\n\n            return (hexEnd, value);\n        }\n    }\n}\n"
      },
      "src/lib/parse/literal/LibParseLiteralSubParseable.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {ParseState} from \"../LibParseState.sol\";\nimport {LibParse} from \"../LibParse.sol\";\nimport {UnclosedSubParseableLiteral, SubParseableMissingDispatch} from \"../../../error/ErrParse.sol\";\nimport {\n    CMASK_WHITESPACE, CMASK_SUB_PARSEABLE_LITERAL_HEAD, CMASK_SUB_PARSEABLE_LITERAL_END\n} from \"../LibParseCMask.sol\";\nimport {LibParseInterstitial} from \"../LibParseInterstitial.sol\";\nimport {LibParseError} from \"../LibParseError.sol\";\nimport {LibSubParse} from \"../LibSubParse.sol\";\n\nlibrary LibParseLiteralSubParseable {\n    using LibParse for ParseState;\n    using LibParseInterstitial for ParseState;\n    using LibParseError for ParseState;\n    using LibSubParse for ParseState;\n\n    /// Parse a sub parseable literal. All sub parseable literals are bounded by\n    /// square brackets, and contain a dispatch and a body. The dispatch is the\n    /// string immediately following the opening bracket, and the body is the\n    /// string immediately following the dispatch, up to the closing bracket.\n    /// The dispatch and body MUST be separated by at least one whitespace char.\n    /// This implies that the dispatch MAY NOT contain any whitespace chars, and\n    /// the body MAY contain any chars except for the closing bracket.\n    /// Leading and trailing whitespace before/after the dispatch/body is NOT\n    /// supported. The former will error and the latter will be treated as part\n    /// of the body.\n    function parseSubParseable(ParseState memory state, uint256 cursor, uint256 end)\n        internal\n        pure\n        returns (uint256, uint256)\n    {\n        unchecked {\n            // Move cursor past opening bracket.\n            // Caller is responsible for checking that the cursor is pointing\n            // at a sub parseable literal.\n            ++cursor;\n\n            uint256 dispatchStart = cursor;\n\n            // Skip all non-whitespace and non-bracket characters.\n            cursor = LibParse.skipMask(cursor, end, ~(CMASK_WHITESPACE | CMASK_SUB_PARSEABLE_LITERAL_END));\n            uint256 dispatchEnd = cursor;\n\n            if (dispatchEnd == dispatchStart) {\n                revert SubParseableMissingDispatch(state.parseErrorOffset(cursor));\n            }\n\n            // Skip any whitespace.\n            cursor = state.skipWhitespace(cursor, end);\n\n            uint256 bodyStart = cursor;\n\n            // Skip all chars til the close.\n            // Note that as multibyte is not supported, and the mask is 128 bits,\n            // non-ascii chars MAY either fail to be skipped or will be treated\n            // as a closing bracket.\n            cursor = LibParse.skipMask(cursor, end, ~CMASK_SUB_PARSEABLE_LITERAL_END);\n            uint256 bodyEnd = cursor;\n\n            {\n                uint256 finalChar;\n                assembly (\"memory-safe\") {\n                    //slither-disable-next-line incorrect-shift\n                    finalChar := shl(byte(0, mload(cursor)), 1)\n                }\n                if ((finalChar & CMASK_SUB_PARSEABLE_LITERAL_END) == 0) {\n                    revert UnclosedSubParseableLiteral(state.parseErrorOffset(cursor));\n                }\n            }\n\n            // Move cursor past closing bracket.\n            ++cursor;\n\n            return (cursor, state.subParseLiteral(dispatchStart, dispatchEnd, bodyStart, bodyEnd));\n        }\n    }\n}\n"
      },
      "lib/rain.interpreter.interface/src/interface/deprecated/IInterpreterV1.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IInterpreterStoreV1} from \"./IInterpreterStoreV1.sol\";\n\n/// @dev The index of a source within a deployed expression that can be evaluated\n/// by an `IInterpreterV1`. MAY be an entrypoint or the index of a source called\n/// internally such as by the `call` opcode.\ntype SourceIndex is uint16;\n\n/// @dev Encoded information about a specific evaluation including the expression\n/// address onchain, entrypoint and expected return values.\ntype EncodedDispatch is uint256;\n\n/// @dev The namespace for state changes as requested by the calling contract.\n/// The interpreter MUST apply this namespace IN ADDITION to namespacing by\n/// caller etc.\ntype StateNamespace is uint256;\n\n/// @dev Additional bytes that can be used to configure a single opcode dispatch.\n/// Commonly used to specify the number of inputs to a variadic function such\n/// as addition or multiplication.\ntype Operand is uint256;\n\n/// @dev The default state namespace MUST be used when a calling contract has no\n/// particular opinion on or need for dynamic namespaces.\nStateNamespace constant DEFAULT_STATE_NAMESPACE = StateNamespace.wrap(0);\n\n/// @title IInterpreterV1\n/// Interface into a standard interpreter that supports:\n///\n/// - evaluating `view` logic deployed onchain by an `IExpressionDeployerV1`\n/// - receiving arbitrary `uint256[][]` supporting context to be made available\n///   to the evaluated logic\n/// - handling subsequent state changes in bulk in response to evaluated logic\n/// - namespacing state changes according to the caller's preferences to avoid\n///   unwanted key collisions\n/// - exposing its internal function pointers to support external precompilation\n///   of logic for more gas efficient runtime evaluation by the interpreter\n///\n/// The interface is designed to be stable across many versions and\n/// implementations of an interpreter, balancing minimalism with features\n/// required for a general purpose onchain interpreted compute environment.\n///\n/// The security model of an interpreter is that it MUST be resilient to\n/// malicious expressions even if they dispatch arbitrary internal function\n/// pointers during an eval. The interpreter MAY return garbage or exhibit\n/// undefined behaviour or error during an eval, _provided that no state changes\n/// are persisted_ e.g. in storage, such that only the caller that specifies the\n/// malicious expression can be negatively impacted by the result. In turn, the\n/// caller must guard itself against arbitrarily corrupt/malicious reverts and\n/// return values from any interpreter that it requests an expression from. And\n/// so on and so forth up to the externally owned account (EOA) who signs the\n/// transaction and agrees to a specific combination of contracts, expressions\n/// and interpreters, who can presumably make an informed decision about which\n/// ones to trust to get the job done.\n///\n/// The state changes for an interpreter are expected to be produces by an `eval`\n/// and passed to the `IInterpreterStoreV1` returned by the eval, as-is by the\n/// caller, after the caller has had an opportunity to apply their own\n/// intermediate logic such as reentrancy defenses against malicious\n/// interpreters. The interpreter is free to structure the state changes however\n/// it wants but MUST guard against the calling contract corrupting the changes\n/// between `eval` and `set`. For example a store could sandbox storage writes\n/// per-caller so that a malicious caller can only damage their own state\n/// changes, while honest callers respect, benefit from and are protected by the\n/// interpreter store's state change handling.\n///\n/// The two step eval-state model allows eval to be read-only which provides\n/// security guarantees for the caller such as no stateful reentrancy, either\n/// from the interpreter or some contract interface used by some word, while\n/// still allowing for storage writes. As the storage writes happen on the\n/// interpreter rather than the caller (c.f. delegate call) the caller DOES NOT\n/// need to trust the interpreter, which allows for permissionless selection of\n/// interpreters by end users. Delegate call always implies an admin key on the\n/// caller because the delegatee contract can write arbitrarily to the state of\n/// the delegator, which severely limits the generality of contract composition.\ninterface IInterpreterV1 {\n    /// Exposes the function pointers as `uint16` values packed into a single\n    /// `bytes` in the same order as they would be indexed into by opcodes. For\n    /// example, if opcode `2` should dispatch function at position `0x1234` then\n    /// the start of the returned bytes would be `0xXXXXXXXX1234` where `X` is\n    /// a placeholder for the function pointers of opcodes `0` and `1`.\n    ///\n    /// `IExpressionDeployerV1` contracts use these function pointers to\n    /// \"compile\" the expression into something that an interpreter can dispatch\n    /// directly without paying gas to lookup the same at runtime. As the\n    /// validity of any integrity check and subsequent dispatch is highly\n    /// sensitive to both the function pointers and overall bytecode of the\n    /// interpreter, `IExpressionDeployerV1` contracts SHOULD implement guards\n    /// against accidentally being deployed onchain paired against an unknown\n    /// interpreter. It is very easy for an apparent compatible pairing to be\n    /// subtly and critically incompatible due to addition/removal/reordering of\n    /// opcodes and compiler optimisations on the interpreter bytecode.\n    ///\n    /// This MAY return different values during construction vs. all other times\n    /// after the interpreter has been successfully deployed onchain. DO NOT rely\n    /// on function pointers reported during contract construction.\n    function functionPointers() external view returns (bytes memory);\n\n    /// The raison d'etre for an interpreter. Given some expression and per-call\n    /// additional contextual data, produce a stack of results and a set of state\n    /// changes that the caller MAY OPTIONALLY pass back to be persisted by a\n    /// call to `IInterpreterStoreV1.set`.\n    /// @param store The storage contract that the returned key/value pairs\n    /// MUST be passed to IF the calling contract is in a non-static calling\n    /// context. Static calling contexts MUST pass `address(0)`.\n    /// @param namespace The state namespace that will be fully qualified by the\n    /// interpreter at runtime in order to perform gets on the underlying store.\n    /// MUST be the same namespace passed to the store by the calling contract\n    /// when sending the resulting key/value items to storage.\n    /// @param dispatch All the information required for the interpreter to load\n    /// an expression, select an entrypoint and return the values expected by the\n    /// caller. The interpreter MAY encode dispatches differently to\n    /// `LibEncodedDispatch` but this WILL negatively impact compatibility for\n    /// calling contracts that hardcode the encoding logic.\n    /// @param context A 2-dimensional array of data that can be indexed into at\n    /// runtime by the interpreter. The calling contract is responsible for\n    /// ensuring the authenticity and completeness of context data. The\n    /// interpreter MUST revert at runtime if an expression attempts to index\n    /// into some context value that is not provided by the caller. This implies\n    /// that context reads cannot be checked for out of bounds reads at deploy\n    /// time, as the runtime context MAY be provided in a different shape to what\n    /// the expression is expecting.\n    /// Same as `eval` but allowing the caller to specify a namespace under which\n    /// the state changes will be applied. The interpeter MUST ensure that keys\n    /// will never collide across namespaces, even if, for example:\n    ///\n    /// - The calling contract is malicious and attempts to craft a collision\n    ///   with state changes from another contract\n    /// - The expression is malicious and attempts to craft a collision with\n    ///   other expressions evaluated by the same calling contract\n    ///\n    /// A malicious entity MAY have access to significant offchain resources to\n    /// attempt to precompute key collisions through brute force. The collision\n    /// resistance of namespaces should be comparable or equivalent to the\n    /// collision resistance of the hashing algorithms employed by the blockchain\n    /// itself, such as the design of `mapping` in Solidity that hashes each\n    /// nested key to produce a collision resistant compound key.\n    /// @return stack The list of values produced by evaluating the expression.\n    /// MUST NOT be longer than the maximum length specified by `dispatch`, if\n    /// applicable.\n    /// @return kvs A list of pairwise key/value items to be saved in the store.\n    function eval(\n        IInterpreterStoreV1 store,\n        StateNamespace namespace,\n        EncodedDispatch dispatch,\n        uint256[][] calldata context\n    ) external view returns (uint256[] memory stack, uint256[] memory kvs);\n}\n"
      },
      "lib/rain.interpreter.interface/src/interface/IInterpreterStoreV2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {StateNamespace, FullyQualifiedNamespace, NO_STORE} from \"./deprecated/IInterpreterStoreV1.sol\";\n\n/// @title IInterpreterStoreV2\n/// @notice Tracks state changes on behalf of an interpreter. A single store can\n/// handle state changes for many calling contracts, many interpreters and many\n/// expressions. The store is responsible for ensuring that applying these state\n/// changes is safe from key collisions with calls to `set` from different\n/// `msg.sender` callers. I.e. it MUST NOT be possible for a caller to modify the\n/// state changes associated with some other caller.\n///\n/// The store defines the shape of its own state changes, which is opaque to the\n/// calling contract. For example, some store may treat the list of state changes\n/// as a pairwise key/value set, and some other store may treat it as a literal\n/// list to be stored as-is.\n///\n/// Each interpreter decides for itself which store to use based on the\n/// compatibility of its own opcodes.\n///\n/// The store MUST assume the state changes have been corrupted by the calling\n/// contract due to bugs or malicious intent, and enforce state isolation between\n/// callers despite arbitrarily invalid state changes. The store MUST revert if\n/// it can detect invalid state changes, such as a key/value list having an odd\n/// number of items, but this MAY NOT be possible if the corruption is\n/// undetectable.\ninterface IInterpreterStoreV2 {\n    /// MUST be emitted by the store on `set` to its internal storage.\n    /// @param namespace The fully qualified namespace that the store is setting.\n    /// @param key The key that the store is setting.\n    /// @param value The value that the store is setting.\n    event Set(FullyQualifiedNamespace namespace, uint256 key, uint256 value);\n\n    /// Mutates the interpreter store in bulk. The bulk values are provided in\n    /// the form of a `uint256[]` which can be treated e.g. as pairwise keys and\n    /// values to be stored in a Solidity mapping. The `IInterpreterStoreV2`\n    /// defines the meaning of the `uint256[]` for its own storage logic.\n    ///\n    /// @param namespace The unqualified namespace for the set that MUST be\n    /// fully qualified by the `IInterpreterStoreV2` to prevent key collisions\n    /// between callers. The fully qualified namespace forms a compound key with\n    /// the keys for each value to set.\n    /// @param kvs The list of changes to apply to the store's internal state.\n    function set(StateNamespace namespace, uint256[] calldata kvs) external;\n\n    /// Given a fully qualified namespace and key, return the associated value.\n    /// Ostensibly the interpreter can use this to implement opcodes that read\n    /// previously set values. The interpreter MUST apply the same qualification\n    /// logic as the store that it uses to guarantee consistent round tripping of\n    /// data and prevent malicious behaviours. Technically also allows onchain\n    /// reads of any set value from any contract, not just interpreters, but in\n    /// this case readers MUST be aware and handle inconsistencies between get\n    /// and set while the state changes are still in memory in the calling\n    /// context and haven't yet been persisted to the store.\n    ///\n    /// `IInterpreterStoreV2` uses the same fallback behaviour for unset keys as\n    /// Solidity. Specifically, any UNSET VALUES SILENTLY FALLBACK TO `0`.\n    /// @param namespace The fully qualified namespace to get a single value for.\n    /// @param key The key to get the value for within the namespace.\n    /// @return The value OR ZERO IF NOT SET.\n    function get(FullyQualifiedNamespace namespace, uint256 key) external view returns (uint256);\n}\n"
      },
      "lib/rain.interpreter.interface/src/lib/bytecode/LibBytecode.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.19;\n\nimport {LibPointer, Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {LibBytes} from \"rain.solmem/lib/LibBytes.sol\";\nimport {LibMemCpy} from \"rain.solmem/lib/LibMemCpy.sol\";\nimport {\n    StackSizingsNotMonotonic,\n    TruncatedSource,\n    UnexpectedTrailingOffsetBytes,\n    TruncatedHeader,\n    TruncatedHeaderOffsets,\n    UnexpectedSources,\n    SourceIndexOutOfBounds\n} from \"../../error/ErrBytecode.sol\";\n\n/// @title LibBytecode\n/// @notice A library for inspecting the bytecode of an expression. Largely\n/// focused on reading the source headers rather than the opcodes themselves.\n/// Designed to be efficient enough to be used in the interpreter directly.\n/// As such, it is not particularly safe, notably it always assumes that the\n/// headers are not lying about the structure and runtime behaviour of the\n/// bytecode. This is by design as it allows much more simple, efficient and\n/// decoupled implementation of authoring/parsing logic, which makes the author\n/// of an expression responsible for producing well formed bytecode, such as\n/// balanced LHS/RHS stacks. The deployment integrity checks are responsible for\n/// checking that the headers match the structure and behaviour of the bytecode.\nlibrary LibBytecode {\n    using LibPointer for Pointer;\n    using LibBytes for bytes;\n    using LibMemCpy for Pointer;\n\n    /// The number of sources in the bytecode.\n    /// If the bytecode is empty, returns 0.\n    /// Otherwise, returns the first byte of the bytecode, which is the number\n    /// of sources.\n    /// Implies that 0x and 0x00 are equivalent, both having 0 sources. For this\n    /// reason, contracts that handle bytecode MUST NOT rely on simple data\n    /// length checks to determine if the bytecode is empty or not.\n    /// DOES NOT check the integrity or even existence of the sources.\n    /// @param bytecode The bytecode to inspect.\n    /// @return count The number of sources in the bytecode.\n    function sourceCount(bytes memory bytecode) internal pure returns (uint256 count) {\n        if (bytecode.length == 0) {\n            return 0;\n        }\n        assembly (\"memory-safe\") {\n            // The first byte of rain bytecode is the count of how many sources\n            // there are.\n            count := byte(0, mload(add(bytecode, 0x20)))\n        }\n    }\n\n    /// Checks the structural integrity of the bytecode from the perspective of\n    /// potential out of bounds reads. Will revert if the bytecode is not\n    /// well-formed. This check MUST be done BEFORE any attempts at per-opcode\n    /// integrity checks, as the per-opcode checks assume that the headers define\n    /// valid regions in memory to iterate over.\n    ///\n    /// Checks:\n    /// - The offsets are populated according to the source count.\n    /// - The offsets point to positions within the bytecode `bytes`.\n    /// - There exists at least the 4 byte header for each source at the offset,\n    ///   within the bounds of the bytecode `bytes`.\n    /// - The number of opcodes specified in the header of each source locates\n    ///   the end of the source exactly at either the offset of the next source\n    ///   or the end of the bytecode `bytes`.\n    function checkNoOOBPointers(bytes memory bytecode) internal pure {\n        unchecked {\n            uint256 count = sourceCount(bytecode);\n            // The common case is that there are more than 0 sources.\n            if (count > 0) {\n                uint256 sourcesRelativeStart = 1 + count * 2;\n                if (sourcesRelativeStart > bytecode.length) {\n                    revert TruncatedHeaderOffsets(bytecode);\n                }\n                uint256 sourcesStart;\n                assembly (\"memory-safe\") {\n                    sourcesStart := add(bytecode, add(0x20, sourcesRelativeStart))\n                }\n\n                // Start at the end of the bytecode and work backwards. Find the\n                // last unchecked relative offset, follow it, read the opcode\n                // count from the header, and check that ends at the end cursor.\n                // Set the end cursor to the relative offset then repeat until\n                // there are no more unchecked relative offsets. The endCursor\n                // as a relative offset must be 0 at the end of this process\n                // (i.e. the first relative offset is always 0).\n                uint256 endCursor;\n                assembly (\"memory-safe\") {\n                    endCursor := add(bytecode, add(0x20, mload(bytecode)))\n                }\n                // This cursor points at the 2 byte relative offset that we need\n                // to check next.\n                uint256 uncheckedOffsetCursor;\n                uint256 end;\n                assembly (\"memory-safe\") {\n                    uncheckedOffsetCursor := add(bytecode, add(0x21, mul(sub(count, 1), 2)))\n                    end := add(bytecode, 0x21)\n                }\n\n                while (uncheckedOffsetCursor >= end) {\n                    // Read the relative offset from the bytecode.\n                    uint256 relativeOffset;\n                    assembly (\"memory-safe\") {\n                        relativeOffset := shr(0xF0, mload(uncheckedOffsetCursor))\n                    }\n                    uint256 absoluteOffset = sourcesStart + relativeOffset;\n\n                    // Check that the 4 byte header is within the upper bound\n                    // established by the end cursor before attempting to read\n                    // from it.\n                    uint256 headerEnd = absoluteOffset + 4;\n                    if (headerEnd > endCursor) {\n                        revert TruncatedHeader(bytecode);\n                    }\n\n                    // The ops count is the first byte of the header.\n                    uint256 opsCount;\n                    {\n                        // The stack allocation, inputs, and outputs are the next\n                        // 3 bytes of the header. We can't know exactly what they\n                        // need to be according to the opcodes without checking\n                        // every opcode implementation, but we can check that\n                        // they satisfy the invariant\n                        // `inputs <= outputs <= stackAllocation`.\n                        // Note that the outputs may include the inputs, as the\n                        // outputs is merely the final stack size.\n                        uint256 stackAllocation;\n                        uint256 inputs;\n                        uint256 outputs;\n                        assembly (\"memory-safe\") {\n                            let data := mload(absoluteOffset)\n                            opsCount := byte(0, data)\n                            stackAllocation := byte(1, data)\n                            inputs := byte(2, data)\n                            outputs := byte(3, data)\n                        }\n\n                        if (inputs > outputs || outputs > stackAllocation) {\n                            revert StackSizingsNotMonotonic(bytecode, relativeOffset);\n                        }\n                    }\n\n                    // The ops count is the number of 4 byte opcodes in the\n                    // source. Check that the end of the source is at the end\n                    // cursor.\n                    uint256 sourceEnd = headerEnd + opsCount * 4;\n                    if (sourceEnd != endCursor) {\n                        revert TruncatedSource(bytecode);\n                    }\n\n                    // Move the end cursor to the start of the header.\n                    endCursor = absoluteOffset;\n                    // Move the unchecked offset cursor to the previous offset.\n                    uncheckedOffsetCursor -= 2;\n                }\n\n                // If the end cursor is not pointing at the absolute start of the\n                // sources, then somehow the bytecode has malformed data between\n                // the offsets and the sources.\n                if (endCursor != sourcesStart) {\n                    revert UnexpectedTrailingOffsetBytes(bytecode);\n                }\n            } else {\n                // If there are no sources the bytecode is either 0 length or a\n                // single 0 byte, which we already implicity checked by reaching\n                // this code path. Ensure the bytecode has no trailing bytes.\n                if (bytecode.length > 1) {\n                    revert UnexpectedSources(bytecode);\n                }\n            }\n        }\n    }\n\n    /// The relative byte offset of a source in the bytecode.\n    /// This is the offset from the start of the first source header, which is\n    /// after the source count byte and the source offsets.\n    /// This function DOES NOT check that the relative offset is within the\n    /// bounds of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE\n    /// attempting to traverse the bytecode, otherwise the relative offset MAY\n    /// point to memory outside the bytecode `bytes`.\n    /// @param bytecode The bytecode to inspect.\n    /// @param sourceIndex The index of the source to inspect.\n    /// @return offset The relative byte offset of the source in the bytecode.\n    function sourceRelativeOffset(bytes memory bytecode, uint256 sourceIndex) internal pure returns (uint256 offset) {\n        // If the source index requested is out of bounds, revert.\n        if (sourceIndex >= sourceCount(bytecode)) {\n            revert SourceIndexOutOfBounds(bytecode, sourceIndex);\n        }\n        assembly (\"memory-safe\") {\n            // After the first byte, all the relative offset pointers are\n            // stored sequentially as 16 bit values.\n            offset := and(mload(add(add(bytecode, 3), mul(sourceIndex, 2))), 0xFFFF)\n        }\n    }\n\n    /// The absolute byte pointer of a source in the bytecode. Points to the\n    /// header of the source, NOT the first opcode.\n    /// This function DOES NOT check that the source index is within the bounds\n    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to\n    /// traverse the bytecode, otherwise the relative offset MAY point to memory\n    /// outside the bytecode `bytes`.\n    /// @param bytecode The bytecode to inspect.\n    /// @param sourceIndex The index of the source to inspect.\n    /// @return pointer The absolute byte pointer of the source in the bytecode.\n    function sourcePointer(bytes memory bytecode, uint256 sourceIndex) internal pure returns (Pointer pointer) {\n        unchecked {\n            uint256 sourcesStartOffset = 1 + sourceCount(bytecode) * 2;\n            uint256 offset = sourceRelativeOffset(bytecode, sourceIndex);\n            assembly (\"memory-safe\") {\n                pointer := add(add(add(bytecode, 0x20), sourcesStartOffset), offset)\n            }\n        }\n    }\n\n    /// The number of opcodes in a source.\n    /// This function DOES NOT check that the source index is within the bounds\n    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to\n    /// traverse the bytecode, otherwise the relative offset MAY point to memory\n    /// outside the bytecode `bytes`.\n    /// @param bytecode The bytecode to inspect.\n    /// @param sourceIndex The index of the source to inspect.\n    /// @return opsCount The number of opcodes in the source.\n    function sourceOpsCount(bytes memory bytecode, uint256 sourceIndex) internal pure returns (uint256 opsCount) {\n        unchecked {\n            Pointer pointer = sourcePointer(bytecode, sourceIndex);\n            assembly (\"memory-safe\") {\n                opsCount := byte(0, mload(pointer))\n            }\n        }\n    }\n\n    /// The number of stack slots allocated by a source. This is the number of\n    /// 32 byte words that MUST be allocated for the stack for the given source\n    /// index to avoid memory corruption when executing the source.\n    /// This function DOES NOT check that the source index is within the bounds\n    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to\n    /// traverse the bytecode, otherwise the relative offset MAY point to memory\n    /// outside the bytecode `bytes`.\n    /// @param bytecode The bytecode to inspect.\n    /// @param sourceIndex The index of the source to inspect.\n    /// @return allocation The number of stack slots allocated by the source.\n    function sourceStackAllocation(bytes memory bytecode, uint256 sourceIndex)\n        internal\n        pure\n        returns (uint256 allocation)\n    {\n        unchecked {\n            Pointer pointer = sourcePointer(bytecode, sourceIndex);\n            assembly (\"memory-safe\") {\n                allocation := byte(1, mload(pointer))\n            }\n        }\n    }\n\n    /// The number of inputs and outputs of a source.\n    /// This function DOES NOT check that the source index is within the bounds\n    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to\n    /// traverse the bytecode, otherwise the relative offset MAY point to memory\n    /// outside the bytecode `bytes`.\n    /// Note that both the inputs and outputs are always returned togther, this\n    /// is because the caller SHOULD be checking both together whenever using\n    /// some bytecode. Returning two values is more efficient than two separate\n    /// function calls.\n    /// @param bytecode The bytecode to inspect.\n    /// @param sourceIndex The index of the source to inspect.\n    /// @return inputs The number of inputs of the source.\n    /// @return outputs The number of outputs of the source.\n    function sourceInputsOutputsLength(bytes memory bytecode, uint256 sourceIndex)\n        internal\n        pure\n        returns (uint256 inputs, uint256 outputs)\n    {\n        unchecked {\n            Pointer pointer = sourcePointer(bytecode, sourceIndex);\n            assembly (\"memory-safe\") {\n                let data := mload(pointer)\n                inputs := byte(2, data)\n                outputs := byte(3, data)\n            }\n        }\n    }\n\n    /// Backwards compatibility with the old way of representing sources.\n    /// Requires allocation and copying so it isn't particularly efficient, but\n    /// allows us to use the new bytecode format with old interpreter code. Not\n    /// recommended for production code but useful for testing.\n    function bytecodeToSources(bytes memory bytecode) internal pure returns (bytes[] memory) {\n        unchecked {\n            uint256 count = sourceCount(bytecode);\n            bytes[] memory sources = new bytes[](count);\n            for (uint256 i = 0; i < count; i++) {\n                // Skip over the prefix 4 bytes.\n                Pointer pointer = sourcePointer(bytecode, i).unsafeAddBytes(4);\n                uint256 length = sourceOpsCount(bytecode, i) * 4;\n                bytes memory source = new bytes(length);\n                pointer.unsafeCopyBytesTo(source.dataPointer(), length);\n                // Move the opcode index one byte for each opcode, into the input\n                // position, as legacly sources did not have input bytes.\n                assembly (\"memory-safe\") {\n                    for {\n                        let cursor := add(source, 0x20)\n                        let end := add(cursor, length)\n                    } lt(cursor, end) { cursor := add(cursor, 4) } {\n                        mstore8(add(cursor, 1), byte(0, mload(cursor)))\n                        mstore8(cursor, 0)\n                    }\n                }\n                sources[i] = source;\n            }\n            return sources;\n        }\n    }\n}\n"
      },
      "lib/rain.interpreter.interface/src/interface/ISubParserV2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n// Reexports for implementations to use.\nimport {AuthoringMetaV2} from \"./IParserV1.sol\";\nimport {Operand} from \"./IInterpreterV2.sol\";\n\n/// @dev A compatibility version for the subparser interface.\n///\n/// ## Literal parsing\n///\n/// The structure of data for this version is:\n/// - bytes [0,1]: The length of the dispatch data as 2 bytes.\n/// - bytes [2,N-1+2]: The dispatch data, where N is the length of the dispatch\n///   data as defined by the first 2 bytes. This is used by the sub parser to\n///   decide which literal parser to use. If there are no matches the sub parser\n///   MUST return false and MUST NOT revert.\n/// - bytes [N+2,...]: The literal data that the sub parser is being asked to\n///   parse. The sub parser MUST revert if it cannot parse the literal, once it\n///   has determined that it is the correct sub parser to handle the literal.\n///\n/// ## Word parsing\n///\n/// The structure of data for this version is:\n/// - bytes [0,1]: The current height of the constants array on the main parser.\n/// - bytes [2,2]: The IO byte, that at the time of writing represents the\n///   number of inputs to the word.\n/// - bytes [3,4]; Two bytes that encodes N where N is the length in bytes of the\n///   rainlang word that could not be parsed in bytes.\n/// - bytes [5, N+5]: A string slice that the parser could not parse. For well\n///   formed rainlang it will be a word WITHOUT any associated operands. The\n///   parsing of operands is handled by the main parser, and the subparser is\n///   only expected to parse the word itself and handle the pre-parsed operand\n///   values.\n/// - bytes [N+5,...]: The operands that the main parser has already parsed as\n///   a standard `uint256[]` array. The subparser is expected to handle these\n///   operands as-is, and return bytecode that is compatible with the operand\n///   values. The first word of the array is the array length.\nbytes32 constant COMPATIBLITY_V2 = keccak256(\"2023.12.28 Rainlang ISubParserV2\");\n\n/// @dev A compatibility version for the subparser interface.\n///\n/// Identical to COMPATIBLITY_V2, except the IO byte in word parsing now encodes\n/// both the inputs and outputs. The IO byte is [2,2] in the word parsing data.\n/// The high/leftmost 4 bits of the IO byte encode the number of outputs, and the\n/// low/rightmost 4 bits of the IO byte encode the number of inputs. This implies\n/// that the number of inputs and outputs must each be less than 16.\nbytes32 constant COMPATIBLITY_V3 = keccak256(\"2024.02.15 Rainlang ISubParserV3\");\n\ninterface ISubParserV2 {\n    /// The sub parser is being asked to attempt to parse a literal that the main\n    /// parser has failed to parse. The sub parser MUST ONLY attempt to parse a\n    /// literal that matches both the compatibility version and that the data\n    /// represents a literal that the sub parser is capable of parsing. It is\n    /// expected that the main parser will attempt multiple sub parsers in order\n    /// to parse a literal, so the sub parser MUST NOT revert if it does not know\n    /// how to parse the literal, as some other sub parser may be able to parse\n    /// it. The sub parser MUST return false if it does not know how to parse the\n    /// literal, and MUST return true if it does know how to parse the literal,\n    /// as well as the value of the literal.\n    /// If the sub parser knows how to parse some literal, but the data is\n    /// malformed, the sub parser MUST revert.\n    /// If the compatibility version is not supported, the sub parser MUST\n    /// revert.\n    ///\n    /// Literal parsing is the process of taking a sequence of bytes and\n    /// converting it into a value that is known at compile time.\n    ///\n    /// @param compatibility The compatibility version of the parser that the\n    /// sub parser must support in order to parse the literal.\n    /// @param data The data that represents the literal. The structure of this\n    /// is defined by the conventions for the compatibility version.\n    /// @return success Whether the sub parser knows how to parse the literal.\n    /// If the sub parser does know how to handle the literal but cannot due to\n    /// malformed data, or some other reason, it MUST revert.\n    /// @return value The value of the literal.\n    function subParseLiteral(bytes32 compatibility, bytes calldata data)\n        external\n        pure\n        returns (bool success, uint256 value);\n\n    /// The sub parser is being asked to attempt to parse a word that the main\n    /// parser has failed to parse. The sub parser MUST ONLY attempt to parse a\n    /// word that matches both the compatibility version and that the data\n    /// represents a word that the sub parser is capable of parsing. It is\n    /// expected that the main parser will attempt multiple sub parsers in order\n    /// to parse a word, so the sub parser MUST NOT revert if it does not know\n    /// how to parse the word, as some other sub parser may be able to parse\n    /// it. The sub parser MUST return false if it does not know how to parse the\n    /// word, and MUST return true if it does know how to parse the word,\n    /// as well as the bytecode and constants of the word.\n    /// If the sub parser knows how to parse some word, but the data is\n    /// malformed, the sub parser MUST revert.\n    ///\n    /// Word parsing is the process of taking a sequence of bytes and\n    /// converting it into a sequence of bytecode and constants that is known at\n    /// compile time, and will be executed at runtime. As the bytecode executes\n    /// on the interpreter, not the (sub)parser, the sub parser relies on\n    /// convention to ensure that it is producing valid bytecode and constants.\n    /// These conventions are defined by the compatibility versions.\n    ///\n    /// @param compatibility The compatibility version of the parser that the\n    /// sub parser must support in order to parse the word.\n    /// @param data The data that represents the word.\n    /// @return success Whether the sub parser knows how to parse the word.\n    /// If the sub parser does know how to handle the word but cannot due to\n    /// malformed data, or some other reason, it MUST revert.\n    /// @return bytecode The bytecode of the word.\n    /// @return constants The constants of the word. This MAY be empty if the\n    /// bytecode does not require any new constants. These constants will be\n    /// merged into the constants of the main parser.\n    function subParseWord(bytes32 compatibility, bytes calldata data)\n        external\n        pure\n        returns (bool success, bytes memory bytecode, uint256[] memory constants);\n}\n"
      },
      "src/lib/extern/LibExtern.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IInterpreterV2, Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\nimport {\n    IInterpreterExternV3,\n    ExternDispatch,\n    EncodedExternDispatch\n} from \"rain.interpreter.interface/interface/IInterpreterExternV3.sol\";\n\n/// @title LibExtern\n/// Defines and implements an encoding and decoding scheme for the data that\n/// controls the behaviour of externs.\nlibrary LibExtern {\n    /// Converts an opcode and operand pair into a single 32-byte word.\n    /// The encoding scheme is:\n    /// - bits [0,16): the operand\n    /// - bits [16,32): the opcode\n    /// IMPORTANT: The encoding process does not check that either the opcode or\n    /// operand fit within 16 bits. This is the responsibility of the caller.\n    function encodeExternDispatch(uint256 opcode, Operand operand) internal pure returns (ExternDispatch) {\n        return ExternDispatch.wrap(opcode << 0x10 | Operand.unwrap(operand));\n    }\n\n    /// Inverse of `encodeExternDispatch`.\n    function decodeExternDispatch(ExternDispatch dispatch) internal pure returns (uint256, Operand) {\n        return (ExternDispatch.unwrap(dispatch) >> 0x10, Operand.wrap(uint16(ExternDispatch.unwrap(dispatch))));\n    }\n\n    /// Encodes an extern address and dispatch pair into a single 32-byte word.\n    /// This is the full data required to actually call an extern contract.\n    /// The encoding scheme is:\n    /// - bits [0,160): the address of the extern contract\n    /// - bits [160,176): the dispatch operand\n    /// - bits [176,192): the dispatch opcode\n    /// Note that the high bits are implied by a correctly encoded\n    /// `ExternDispatch`. Use `encodeExternDispatch` to ensure this.\n    /// IMPORTANT: The encoding process does not check that any of the values\n    /// fit within their respective bit ranges. This is the responsibility of\n    /// the caller.\n    function encodeExternCall(IInterpreterExternV3 extern, ExternDispatch dispatch)\n        internal\n        pure\n        returns (EncodedExternDispatch)\n    {\n        return EncodedExternDispatch.wrap(uint256(uint160(address(extern))) | ExternDispatch.unwrap(dispatch) << 160);\n    }\n\n    /// Inverse of `encodeExternCall`.\n    function decodeExternCall(EncodedExternDispatch dispatch)\n        internal\n        pure\n        returns (IInterpreterExternV3, ExternDispatch)\n    {\n        return (\n            IInterpreterExternV3(address(uint160(EncodedExternDispatch.unwrap(dispatch)))),\n            ExternDispatch.wrap(EncodedExternDispatch.unwrap(dispatch) >> 160)\n        );\n    }\n}\n"
      },
      "lib/rain.interpreter.interface/src/interface/IInterpreterExternV3.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {EncodedExternDispatch, ExternDispatch} from \"./deprecated/IInterpreterExternV2.sol\";\n\n/// @title IInterpreterExternV3\n/// Handle a single dispatch from some calling contract with an array of\n/// inputs and array of outputs. Ostensibly useful to build \"word packs\" for\n/// `IInterpreterV2` so that less frequently used words can be provided in\n/// a less efficient format, but without bloating the base interpreter in\n/// terms of code size. Effectively allows unlimited words to exist as externs\n/// alongside interpreters.\n///\n/// The difference between V2 and V3 is that V3 integrates with integrity checks.\ninterface IInterpreterExternV3 {\n    /// Checks the integrity of some extern call.\n    /// @param dispatch Encoded information about the extern to dispatch.\n    /// Analogous to the opcode/operand in the interpreter.\n    /// @param expectedInputs The number of inputs expected for the dispatched\n    /// logic.\n    /// @param expectedOutputs The number of outputs expected for the dispatched\n    /// logic.\n    /// @return actualInputs The actual number of inputs for the dispatched\n    /// logic.\n    /// @return actualOutputs The actual number of outputs for the dispatched\n    /// logic.\n    function externIntegrity(ExternDispatch dispatch, uint256 expectedInputs, uint256 expectedOutputs)\n        external\n        view\n        returns (uint256 actualInputs, uint256 actualOutputs);\n\n    /// Handles a single dispatch.\n    /// @param dispatch Encoded information about the extern to dispatch.\n    /// Analogous to the opcode/operand in the interpreter.\n    /// @param inputs The array of inputs for the dispatched logic.\n    /// @return outputs The result of the dispatched logic.\n    function extern(ExternDispatch dispatch, uint256[] calldata inputs)\n        external\n        view\n        returns (uint256[] calldata outputs);\n}\n"
      },
      "src/error/ErrSubParse.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev When a subparser is not compatible with the main parser it MUST error\n/// on `subParse` calls rather than simply return false.\nerror IncompatibleSubParser();\n\n/// @dev Thrown when a subparser is asked to build an extern dispatch when the\n/// constants height is outside the range a single byte can represent.\nerror ExternDispatchConstantsHeightOverflow(uint256 constantsHeight);\n"
      },
      "lib/rain.solmem/src/error/ErrUint256Array.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// Thrown if a truncated length is longer than the array being truncated. It is\n/// not possible to truncate something and increase its length as the memory\n/// region after the array MAY be allocated for something else already.\nerror OutOfBoundsTruncate(uint256 arrayLength, uint256 truncatedLength);\n"
      },
      "src/error/ErrIntegrity.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.19;\n\n/// @dev There are more entrypoints defined by the minimum stack outputs than\n/// there are provided sources. This means the calling contract WILL attempt to\n/// eval a dangling reference to a non-existent source at some point, so this\n/// MUST REVERT.\nerror EntrypointMissing(uint256 expectedEntrypoints, uint256 actualEntrypoints);\n\n/// Thrown when some entrypoint has non-zero inputs. This is not allowed as\n/// only internal dispatches can have source level inputs.\nerror EntrypointNonZeroInput(uint256 entrypointIndex, uint256 inputsLength);\n\n/// The bytecode and integrity function disagree on number of inputs.\nerror BadOpInputsLength(uint256 opIndex, uint256 calculatedInputs, uint256 bytecodeInputs);\n\n/// The bytecode and integrity function disagree on number of outputs.\nerror BadOpOutputsLength(uint256 opIndex, uint256 calculatedOutputs, uint256 bytecodeOutputs);\n\n/// The stack underflowed during integrity check.\nerror StackUnderflow(uint256 opIndex, uint256 stackIndex, uint256 calculatedInputs);\n\n/// The stack underflowed the highwater during integrity check.\nerror StackUnderflowHighwater(uint256 opIndex, uint256 stackIndex, uint256 stackHighwater);\n\n/// The bytecode stack allocation does not match the allocation calculated by\n/// the integrity check.\nerror StackAllocationMismatch(uint256 stackMaxIndex, uint256 bytecodeAllocation);\n\n/// The final stack index does not match the bytecode outputs.\nerror StackOutputsMismatch(uint256 stackIndex, uint256 bytecodeOutputs);\n"
      },
      "lib/rain.lib.memkv/src/lib/LibMemoryKV.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// Entrypoint into the key/value store. Is a mutable pointer to the head of the\n/// linked list. Initially points to `0` for an empty list. The total word count\n/// of all inserts is also encoded alongside the pointer to allow efficient O(1)\n/// memory allocation for a `uint256[]` in the case of a final snapshot/export.\ntype MemoryKV is uint256;\n\n/// The key associated with the value for each item in the store.\ntype MemoryKVKey is uint256;\n\n/// The value associated with the key for each item in the store.\ntype MemoryKVVal is uint256;\n\n/// @title LibMemoryKV\nlibrary LibMemoryKV {\n    /// Gets the value associated with a given key.\n    /// The value returned will be `0` if the key exists and was set to zero OR\n    /// the key DOES NOT exist, i.e. was never set.\n    ///\n    /// The caller MUST check the `exists` flag to disambiguate between zero\n    /// values and unset keys.\n    ///\n    /// @param kv The entrypoint to the key/value store.\n    /// @param key The key to lookup a `value` for.\n    /// @return exists `0` if the key was not found. The `value` MUST NOT be\n    /// used if the `key` does not exist.\n    /// @return value The value for the `key`, if it exists, else `0`. MAY BE `0`\n    /// even if the `key` exists. It is possible to set any key to a `0` value.\n    function get(MemoryKV kv, MemoryKVKey key) internal pure returns (uint256 exists, MemoryKVVal value) {\n        assembly (\"memory-safe\") {\n            // Hash to find the internal linked list to walk.\n            // Hash logic MUST match set.\n            mstore(0, key)\n            let bitOffset := mul(mod(keccak256(0, 0x20), 15), 0x10)\n\n            // Loop until k found or give up if pointer is zero.\n            for { let pointer := and(shr(bitOffset, kv), 0xFFFF) } iszero(iszero(pointer)) {\n                pointer := mload(add(pointer, 0x40))\n            } {\n                if eq(key, mload(pointer)) {\n                    exists := 1\n                    value := mload(add(pointer, 0x20))\n                    break\n                }\n            }\n        }\n    }\n\n    /// Upserts a value in the set by its key. I.e. if the key exists then the\n    /// associated value will be mutated in place, else a new key/value pair will\n    /// be inserted. The key/value store pointer will be mutated and returned as\n    /// it MAY point to a new list item in memory.\n    /// @param kv The key/value store pointer to modify.\n    /// @param key The key to upsert against.\n    /// @param value The value to associate with the upserted key.\n    /// @return The final value of `kv` as it MAY be modified if the upsert\n    /// resulted in an insert operation.\n    function set(MemoryKV kv, MemoryKVKey key, MemoryKVVal value) internal pure returns (MemoryKV) {\n        assembly (\"memory-safe\") {\n            // Hash to spread inserts across internal lists.\n            // This MUST remain in sync with `get` logic.\n            mstore(0, key)\n            let bitOffset := mul(mod(keccak256(0, 0x20), 15), 0x10)\n\n            // Set aside the starting pointer as we'll need to include it in any\n            // newly inserted linked list items.\n            let startPointer := and(shr(bitOffset, kv), 0xFFFF)\n\n            // Find a key match then break so that we populate a nonzero pointer.\n            let pointer := startPointer\n            for {} iszero(iszero(pointer)) { pointer := mload(add(pointer, 0x40)) } {\n                if eq(key, mload(pointer)) { break }\n            }\n\n            // If the pointer is nonzero we have to update the associated value\n            // directly, otherwise this is an insert operation.\n            switch iszero(pointer)\n            // Update.\n            case 0 { mstore(add(pointer, 0x20), value) }\n            // Insert.\n            default {\n                // Allocate 3 words of memory.\n                pointer := mload(0x40)\n                mstore(0x40, add(pointer, 0x60))\n\n                // Write key/value/pointer.\n                mstore(pointer, key)\n                mstore(add(pointer, 0x20), value)\n                mstore(add(pointer, 0x40), startPointer)\n\n                // Update total stored word count.\n                let length := add(shr(0xf0, kv), 2)\n\n                //slither-disable-next-line incorrect-shift\n                kv := or(shl(0xf0, length), and(kv, not(shl(0xf0, 0xFFFF))))\n\n                // kv must point to new insertion.\n                //slither-disable-next-line incorrect-shift\n                kv :=\n                    or(\n                        shl(bitOffset, pointer),\n                        // Mask out the old pointer\n                        and(kv, not(shl(bitOffset, 0xFFFF)))\n                    )\n            }\n        }\n        return kv;\n    }\n\n    /// Export/snapshot the underlying linked list of the key/value store into\n    /// a standard `uint256[]`. Reads the total length to preallocate the\n    /// `uint256[]` then bisects the bits of the `kv` to find non-zero pointers\n    /// to linked lists, walking each found list to the end to extract all\n    /// values. As a single `kv` has 15 slots for pointers to linked lists it is\n    /// likely for smallish structures that many slots can simply be skipped, so\n    /// the bisect approach can save ~1-1.5k gas vs. a naive linear loop over\n    /// all 15 slots for every export.\n    ///\n    /// Note this is a one time export, if the key/value store is subsequently\n    /// mutated the built array will not reflect these mutations.\n    ///\n    /// @param kv The entrypoint into the key/value store.\n    /// @return array All the keys and values copied pairwise into a `uint256[]`.\n    /// Slither is not wrong about the cyclomatic complexity but I don't know\n    /// another way to implement the bisect and keep the gas savings.\n    //slither-disable-next-line cyclomatic-complexity\n    function toUint256Array(MemoryKV kv) internal pure returns (uint256[] memory array) {\n        uint256 mask16 = type(uint16).max;\n        uint256 mask32 = type(uint32).max;\n        uint256 mask64 = type(uint64).max;\n        uint256 mask128 = type(uint128).max;\n        assembly (\"memory-safe\") {\n            // Manually create an `uint256[]`.\n            // No need to zero out memory as we're about to write to it.\n            array := mload(0x40)\n            let length := shr(0xf0, kv)\n            mstore(0x40, add(array, add(0x20, mul(length, 0x20))))\n            mstore(array, length)\n\n            // Known false positives in slither\n            // https://github.com/crytic/slither/issues/1815\n            //slither-disable-next-line naming-convention\n            function copyFromPtr(cursor, pointer) -> end {\n                for {} iszero(iszero(pointer)) {\n                    pointer := mload(add(pointer, 0x40))\n                    cursor := add(cursor, 0x40)\n                } {\n                    mstore(cursor, mload(pointer))\n                    mstore(add(cursor, 0x20), mload(add(pointer, 0x20)))\n                }\n                end := cursor\n            }\n\n            // Bisect.\n            // This crazy tree saves ~1-1.5k gas vs. a simple loop with larger\n            // relative savings for small-medium sized structures.\n            // The internal scoping blocks are to provide some safety against\n            // typos causing the incorrect symbol to be referenced by enforcing\n            // each symbol is as tightly scoped as it can be.\n            let cursor := add(array, 0x20)\n            {\n                // Remove the length from kv before iffing to save ~100 gas.\n                let p0 := shr(0x90, shl(0x10, kv))\n                if iszero(iszero(p0)) {\n                    {\n                        let p00 := shr(0x40, p0)\n                        if iszero(iszero(p00)) {\n                            {\n                                // This branch is a special case because we\n                                // already zeroed out the high bits which are\n                                // used by the length and are NOT a pointer.\n                                // We can skip processing where the pointer would\n                                // have been if it were not the length, and do\n                                // not need to scrub the high bits to move from\n                                // `p00` to `p0001`.\n                                let p0001 := shr(0x20, p00)\n                                if iszero(iszero(p0001)) { cursor := copyFromPtr(cursor, p0001) }\n                            }\n                            let p001 := and(mask32, p00)\n                            if iszero(iszero(p001)) {\n                                {\n                                    let p0010 := shr(0x10, p001)\n                                    if iszero(iszero(p0010)) { cursor := copyFromPtr(cursor, p0010) }\n                                }\n                                let p0011 := and(mask16, p001)\n                                if iszero(iszero(p0011)) { cursor := copyFromPtr(cursor, p0011) }\n                            }\n                        }\n                    }\n                    let p01 := and(mask64, p0)\n                    if iszero(iszero(p01)) {\n                        {\n                            let p010 := shr(0x20, p01)\n                            if iszero(iszero(p010)) {\n                                {\n                                    let p0100 := shr(0x10, p010)\n                                    if iszero(iszero(p0100)) { cursor := copyFromPtr(cursor, p0100) }\n                                }\n                                let p0101 := and(mask16, p010)\n                                if iszero(iszero(p0101)) { cursor := copyFromPtr(cursor, p0101) }\n                            }\n                        }\n\n                        let p011 := and(mask32, p01)\n                        if iszero(iszero(p011)) {\n                            {\n                                let p0110 := shr(0x10, p011)\n                                if iszero(iszero(p0110)) { cursor := copyFromPtr(cursor, p0110) }\n                            }\n\n                            let p0111 := and(mask16, p011)\n                            if iszero(iszero(p0111)) { cursor := copyFromPtr(cursor, p0111) }\n                        }\n                    }\n                }\n            }\n\n            {\n                let p1 := and(mask128, kv)\n                if iszero(iszero(p1)) {\n                    {\n                        let p10 := shr(0x40, p1)\n                        if iszero(iszero(p10)) {\n                            {\n                                let p100 := shr(0x20, p10)\n                                if iszero(iszero(p100)) {\n                                    {\n                                        let p1000 := shr(0x10, p100)\n                                        if iszero(iszero(p1000)) { cursor := copyFromPtr(cursor, p1000) }\n                                    }\n                                    let p1001 := and(mask16, p100)\n                                    if iszero(iszero(p1001)) { cursor := copyFromPtr(cursor, p1001) }\n                                }\n                            }\n                            let p101 := and(mask32, p10)\n                            if iszero(iszero(p101)) {\n                                {\n                                    let p1010 := shr(0x10, p101)\n                                    if iszero(iszero(p1010)) { cursor := copyFromPtr(cursor, p1010) }\n                                }\n                                let p1011 := and(mask16, p101)\n                                if iszero(iszero(p1011)) { cursor := copyFromPtr(cursor, p1011) }\n                            }\n                        }\n                    }\n                    let p11 := and(mask64, p1)\n                    if iszero(iszero(p11)) {\n                        {\n                            let p110 := shr(0x20, p11)\n                            if iszero(iszero(p110)) {\n                                {\n                                    let p1100 := shr(0x10, p110)\n                                    if iszero(iszero(p1100)) { cursor := copyFromPtr(cursor, p1100) }\n                                }\n                                let p1101 := and(mask16, p110)\n                                if iszero(iszero(p1101)) { cursor := copyFromPtr(cursor, p1101) }\n                            }\n                        }\n\n                        let p111 := and(mask32, p11)\n                        if iszero(iszero(p111)) {\n                            {\n                                let p1110 := shr(0x10, p111)\n                                if iszero(iszero(p1110)) { cursor := copyFromPtr(cursor, p1110) }\n                            }\n\n                            let p1111 := and(mask16, p111)\n                            if iszero(iszero(p1111)) { cursor := copyFromPtr(cursor, p1111) }\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
      },
      "src/error/ErrExtern.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572\ncontract ErrExtern {}\n\n/// Thrown when the extern interface is not supported.\nerror NotAnExternContract(address extern);\n\n/// Thrown by the extern contract at runtime when the inputs don't match the\n/// expected inputs.\n/// @param expected The expected number of inputs.\n/// @param actual The actual number of inputs.\nerror BadInputs(uint256 expected, uint256 actual);\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n    // As per the EIP-165 spec, no interface should ever match 0xffffffff\n    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n    /**\n     * @dev Returns true if `account` supports the {IERC165} interface.\n     */\n    function supportsERC165(address account) internal view returns (bool) {\n        // Any contract that implements ERC165 must explicitly indicate support of\n        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n        return\n            supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\n            !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\n    }\n\n    /**\n     * @dev Returns true if `account` supports the interface defined by\n     * `interfaceId`. Support for {IERC165} itself is queried automatically.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n        // query support of both ERC165 as per the spec and support of _interfaceId\n        return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\n    }\n\n    /**\n     * @dev Returns a boolean array where each value corresponds to the\n     * interfaces passed in and whether they're supported or not. This allows\n     * you to batch check interfaces for a contract where your expectation\n     * is that some interfaces may not be supported.\n     *\n     * See {IERC165-supportsInterface}.\n     *\n     * _Available since v3.4._\n     */\n    function getSupportedInterfaces(\n        address account,\n        bytes4[] memory interfaceIds\n    ) internal view returns (bool[] memory) {\n        // an array of booleans corresponding to interfaceIds and whether they're supported or not\n        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n        // query support of ERC165 itself\n        if (supportsERC165(account)) {\n            // query support of each interface in interfaceIds\n            for (uint256 i = 0; i < interfaceIds.length; i++) {\n                interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\n            }\n        }\n\n        return interfaceIdsSupported;\n    }\n\n    /**\n     * @dev Returns true if `account` supports all the interfaces defined in\n     * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n     *\n     * Batch-querying can lead to gas savings by skipping repeated checks for\n     * {IERC165} support.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n        // query support of ERC165 itself\n        if (!supportsERC165(account)) {\n            return false;\n        }\n\n        // query support of each interface in interfaceIds\n        for (uint256 i = 0; i < interfaceIds.length; i++) {\n            if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\n                return false;\n            }\n        }\n\n        // all interfaces supported\n        return true;\n    }\n\n    /**\n     * @notice Query if a contract implements an interface, does not check ERC165 support\n     * @param account The address of the contract to query for support of an interface\n     * @param interfaceId The interface identifier, as specified in ERC-165\n     * @return true if the contract at account indicates support of the interface with\n     * identifier interfaceId, false otherwise\n     * @dev Assumes that account contains a contract that supports ERC165, otherwise\n     * the behavior of this method is undefined. This precondition can be checked\n     * with {supportsERC165}.\n     *\n     * Some precompiled contracts will falsely indicate support for a given interface, so caution\n     * should be exercised when using this function.\n     *\n     * Interface identification is specified in ERC-165.\n     */\n    function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\n        // prepare call\n        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n        // perform static call\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly {\n            success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0x00)\n        }\n\n        return success && returnSize >= 0x20 && returnValue > 0;\n    }\n}\n"
      },
      "src/error/ErrBitwise.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572\ncontract ErrBitwise {}\n\n/// Thrown during integrity check when a bitwise shift operation is attempted\n/// with a shift amount greater than 255 or 0. As the shift amount is taken from\n/// the operand, this is a compile time error so there's no need to support\n/// behaviour that would always evaluate to 0 or be a noop.\nerror UnsupportedBitwiseShiftAmount(uint256 shiftAmount);\n\n/// Thrown during integrity check when bitwise (en|de)coding would be truncated\n/// due to the end bit position being beyond 256.\n/// @param startBit The start of the OOB encoding.\n/// @param length The length of the OOB encoding.\nerror TruncatedBitwiseEncoding(uint256 startBit, uint256 length);\n\n/// Thrown during integrity check when the length of a bitwise (en|de)coding\n/// would be 0.\nerror ZeroLengthBitwiseEncoding();\n"
      },
      "src/lib/eval/LibEvalNP.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibInterpreterStateNP, InterpreterStateNP} from \"../state/LibInterpreterStateNP.sol\";\n\nimport {LibMemCpy} from \"rain.solmem/lib/LibMemCpy.sol\";\nimport {LibMemoryKV, MemoryKV} from \"rain.lib.memkv/lib/LibMemoryKV.sol\";\nimport {LibBytecode} from \"rain.interpreter.interface/lib/bytecode/LibBytecode.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {Operand} from \"rain.interpreter.interface/interface/IInterpreterV2.sol\";\n\n/// Thrown when the inputs length does not match the expected inputs length.\n/// @param expected The expected number of inputs.\n/// @param actual The actual number of inputs.\nerror InputsLengthMismatch(uint256 expected, uint256 actual);\n\nlibrary LibEvalNP {\n    using LibMemoryKV for MemoryKV;\n\n    function evalLoopNP(\n        InterpreterStateNP memory state,\n        uint256 parentSourceIndex,\n        Pointer stackTop,\n        Pointer stackBottom\n    ) internal view returns (Pointer) {\n        uint256 sourceIndex = state.sourceIndex;\n        uint256 cursor;\n        uint256 end;\n        uint256 m;\n        uint256 fPointersStart;\n        // We mod the indexes with the fsCount for each lookup to ensure that\n        // the indexes are in bounds. A mod is cheaper than a bounds check.\n        uint256 fsCount = state.fs.length / 2;\n        {\n            bytes memory bytecode = state.bytecode;\n            bytes memory fPointers = state.fs;\n            assembly (\"memory-safe\") {\n                // SourceIndex is a uint16 so needs cleaning.\n                sourceIndex := and(sourceIndex, 0xFFFF)\n                // Cursor starts at the beginning of the source.\n                cursor := add(bytecode, 0x20)\n                let sourcesLength := byte(0, mload(cursor))\n                cursor := add(cursor, 1)\n                // Find start of sources.\n                let sourcesStart := add(cursor, mul(sourcesLength, 2))\n                // Find relative pointer to source.\n                let sourcesPointer := shr(0xf0, mload(add(cursor, mul(sourceIndex, 2))))\n                // Move cursor to start of source.\n                cursor := add(sourcesStart, sourcesPointer)\n                // Calculate the end.\n                let opsLength := byte(0, mload(cursor))\n                // Move cursor past 4 byte source prefix.\n                cursor := add(cursor, 4)\n\n                // Calculate the mod `m` which is the portion of the source\n                // that can't be copied in 32 byte chunks.\n                m := mod(opsLength, 8)\n\n                // Each op is 4 bytes, and there's a 4 byte prefix for the\n                // source. The initial end is only what can be processed in\n                // 32 byte chunks.\n                end := add(cursor, mul(sub(opsLength, m), 4))\n\n                fPointersStart := add(fPointers, 0x20)\n            }\n        }\n\n        function(InterpreterStateNP memory, Operand, Pointer)\n                    internal\n                    view\n                    returns (Pointer) f;\n        Operand operand;\n        uint256 word;\n        while (cursor < end) {\n            assembly (\"memory-safe\") {\n                word := mload(cursor)\n            }\n\n            // Process high bytes [28, 31]\n            // f needs to be looked up from the fn pointers table.\n            // operand is 3 bytes.\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(0, word), fsCount), 2))))\n                operand := and(shr(0xe0, word), 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            // Bytes [24, 27].\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(4, word), fsCount), 2))))\n                operand := and(shr(0xc0, word), 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            // Bytes [20, 23].\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(8, word), fsCount), 2))))\n                operand := and(shr(0xa0, word), 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            // Bytes [16, 19].\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(12, word), fsCount), 2))))\n                operand := and(shr(0x80, word), 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            // Bytes [12, 15].\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(16, word), fsCount), 2))))\n                operand := and(shr(0x60, word), 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            // Bytes [8, 11].\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(20, word), fsCount), 2))))\n                operand := and(shr(0x40, word), 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            // Bytes [4, 7].\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(24, word), fsCount), 2))))\n                operand := and(shr(0x20, word), 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            // Bytes [0, 3].\n            assembly (\"memory-safe\") {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(28, word), fsCount), 2))))\n                operand := and(word, 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n\n            cursor += 0x20;\n        }\n\n        // Loop over the remainder.\n        // Need to shift the cursor back 28 bytes so that we're reading from\n        // its 4 low bits rather than high bits, to make the loop logic more\n        // efficient.\n        cursor -= 0x1c;\n        end = cursor + m * 4;\n        while (cursor < end) {\n            assembly (\"memory-safe\") {\n                word := mload(cursor)\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(byte(28, word), fsCount), 2))))\n                // 3 bytes mask.\n                operand := and(word, 0xFFFFFF)\n            }\n            stackTop = f(state, operand, stackTop);\n            cursor += 4;\n        }\n\n        LibInterpreterStateNP.stackTrace(parentSourceIndex, sourceIndex, stackTop, stackBottom);\n\n        return stackTop;\n    }\n\n    function eval2(InterpreterStateNP memory state, uint256[] memory inputs, uint256 maxOutputs)\n        internal\n        view\n        returns (uint256[] memory, uint256[] memory)\n    {\n        unchecked {\n            // Use the bytecode's own definition of its IO. Clear example of\n            // how the bytecode could accidentally or maliciously force OOB reads\n            // if the integrity check is not run.\n            (uint256 sourceInputs, uint256 sourceOutputs) =\n                LibBytecode.sourceInputsOutputsLength(state.bytecode, state.sourceIndex);\n\n            Pointer stackBottom;\n            Pointer stackTop;\n            {\n                stackBottom = state.stackBottoms[state.sourceIndex];\n                stackTop = stackBottom;\n                // Copy inputs into place if needed.\n                if (inputs.length > 0) {\n                    // Inline some logic to avoid jumping due to function calls\n                    // on hot path.\n                    Pointer inputsDataPointer;\n                    assembly (\"memory-safe\") {\n                        // Move stack top by the number of inputs.\n                        stackTop := sub(stackTop, mul(mload(inputs), 0x20))\n                        inputsDataPointer := add(inputs, 0x20)\n                    }\n                    LibMemCpy.unsafeCopyWordsTo(inputsDataPointer, stackTop, inputs.length);\n                } else if (inputs.length != sourceInputs) {\n                    revert InputsLengthMismatch(sourceInputs, inputs.length);\n                }\n            }\n\n            // Run the loop.\n            // Parent source index and child are the same at the root eval.\n            stackTop = evalLoopNP(state, state.sourceIndex, stackTop, stackBottom);\n\n            // Convert the stack top pointer to an array with the correct length.\n            // If the stack top is pointing to the base of Solidity's understanding\n            // of the stack array, then this will simply write the same length over\n            // the length the stack was initialized with, otherwise a shorter array\n            // will be built within the bounds of the stack. After this point `tail`\n            // and the original stack MUST be immutable as they're both pointing to\n            // the same memory region.\n            uint256 outputs = maxOutputs < sourceOutputs ? maxOutputs : sourceOutputs;\n            uint256[] memory stack;\n            assembly (\"memory-safe\") {\n                stack := sub(stackTop, 0x20)\n                mstore(stack, outputs)\n            }\n\n            return (stack, state.stateKV.toUint256Array());\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\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    /**\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 `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC5313.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5313.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface for the Light Contract Ownership Standard.\n *\n * A standardized minimal interface required to identify an account that controls a contract\n *\n * _Available since v4.9._\n */\ninterface IERC5313 {\n    /**\n     * @dev Gets the address of the owner.\n     */\n    function owner() external view returns (address);\n}\n"
      },
      "lib/rain.intorastring/src/lib/LibIntOrAString.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.19;\n\n/// @dev This masks out the top 3 bits of a uint256, leaving the lower 253 bits\n/// intact. This ensures the length never exceeds 31 bytes when converting to\n/// and from strings.\nuint256 constant INT_OR_A_STRING_MASK = ~(uint256(7) << 253);\n\n/// Represents string data as an unsigned 32 byte integer. The highest 3 bits are\n/// ignored when interpreting the integer as a string length, naturally limiting\n/// the length of the string to 31 bytes. The lowest 31 bytes are the string\n/// data, with the leftmost byte being the first byte of the string.\n///\n/// If lengths greater than 31 bytes are attempted to be stored, the string\n/// conversion will exhibit the \"weird\" behaviour of truncating the output to\n/// modulo 32 of the length. If the caller wishes to avoid this behaviour, they\n/// should check and error on lengths greater than 31 bytes.\ntype IntOrAString is uint256;\n\n/// @title LibIntOrAString\n/// @notice A library for converting between `IntOrAString` and `string`.\n/// Note that unlike analogous libraries such as Open Zepplin's `ShortStrings`,\n/// there is no intention to provide fallbacks for strings longer than 31 bytes.\n/// The expectation is that `IntOrAString` will be used in contexts where there\n/// really is no sensible fallback, because there is ONLY 32 bytes of space\n/// available, such as a single storage slot or a single evm word on the stack or\n/// in memory. By not supporting fallbacks, we can provide a simpler and more\n/// efficient library, at the expense of requiring all strings to be shorter than\n/// 32 bytes. If strings are longer than 31 bytes, the library will truncate the\n/// output to modulo 32 of the length, which is probably not what you want, so\n/// you should try to avoid ever working with longer strings, e.g. by checking\n/// the length and erroring if it is too long, or otherwise providing the same\n/// guarantee.\nlibrary LibIntOrAString {\n    /// Converts an `IntOrAString` to a `string`, truncating the length to modulo\n    /// 32 of the leftmost byte. Much in the same way as converting `bytes` to\n    /// a string, there are NO checks or guarantees that the string is valid\n    /// according to some encoding such as UTF-8 or ASCII. If the `intOrAString`\n    /// contains garbage bytes beyond its string length, these will be copied\n    /// into the output string, also beyond its string length. For most use cases\n    /// this is fine, as strings aren't typically read beyond their length, but\n    /// it is something to be aware of if those garbage bytes are sensitive\n    /// somehow. The `fromString` function will always zero out these bytes\n    /// beyond the string length, so if the `intOrAString` was created from a\n    /// string using this library, there won't be any non-zero bytes beyond the\n    /// length.\n    function toString(IntOrAString intOrAString) internal pure returns (string memory) {\n        string memory s;\n        uint256 mask = INT_OR_A_STRING_MASK;\n        assembly (\"memory-safe\") {\n            // Point s to the free memory region.\n            s := mload(0x40)\n            // Allocate 64 bytes for the string, including the length field. As\n            // the input data is 32 bytes always, this is always enough.\n            mstore(0x40, add(s, 0x40))\n            // Zero out the region allocated for the string so no garbage data\n            // pre-allocation is present in the final string.\n            mstore(s, 0)\n            mstore(add(s, 0x20), 0)\n            // Copy the input data to the string. As the length is masked to 5\n            // bits, this is always safe in that the length of the output string\n            // won't exceed the length of the original input data.\n            mstore(add(s, 0x1F), and(intOrAString, mask))\n        }\n        return s;\n    }\n\n    /// Converts a `string` to an `IntOrAString`, truncating the length to modulo\n    /// 32 in the process. Any bytes beyond the length of the string will be\n    /// zeroed out, to ensure that no potentially sensitive data in memory is\n    /// copied into the `IntOrAString`.\n    function fromString(string memory s) internal pure returns (IntOrAString) {\n        IntOrAString intOrAString;\n        uint256 mask = INT_OR_A_STRING_MASK;\n        assembly (\"memory-safe\") {\n            intOrAString := and(mload(add(s, 0x1F)), mask)\n            let garbageLength := sub(0x1F, byte(0, intOrAString))\n            //slither-disable-next-line incorrect-shift\n            let garbageMask := not(sub(shl(mul(garbageLength, 8), 1), 1))\n            intOrAString := and(intOrAString, garbageMask)\n        }\n        return intOrAString;\n    }\n}\n"
      },
      "lib/prb-math/src/UD60x18.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\n/*\n\n██████╗ ██████╗ ██████╗ ███╗   ███╗ █████╗ ████████╗██╗  ██╗\n██╔══██╗██╔══██╗██╔══██╗████╗ ████║██╔══██╗╚══██╔══╝██║  ██║\n██████╔╝██████╔╝██████╔╝██╔████╔██║███████║   ██║   ███████║\n██╔═══╝ ██╔══██╗██╔══██╗██║╚██╔╝██║██╔══██║   ██║   ██╔══██║\n██║     ██║  ██║██████╔╝██║ ╚═╝ ██║██║  ██║   ██║   ██║  ██║\n╚═╝     ╚═╝  ╚═╝╚═════╝ ╚═╝     ╚═╝╚═╝  ╚═╝   ╚═╝   ╚═╝  ╚═╝\n\n██╗   ██╗██████╗  ██████╗  ██████╗ ██╗  ██╗ ██╗ █████╗\n██║   ██║██╔══██╗██╔════╝ ██╔═████╗╚██╗██╔╝███║██╔══██╗\n██║   ██║██║  ██║███████╗ ██║██╔██║ ╚███╔╝ ╚██║╚█████╔╝\n██║   ██║██║  ██║██╔═══██╗████╔╝██║ ██╔██╗  ██║██╔══██╗\n╚██████╔╝██████╔╝╚██████╔╝╚██████╔╝██╔╝ ██╗ ██║╚█████╔╝\n ╚═════╝ ╚═════╝  ╚═════╝  ╚═════╝ ╚═╝  ╚═╝ ╚═╝ ╚════╝\n\n*/\n\nimport \"./ud60x18/Casting.sol\";\nimport \"./ud60x18/Constants.sol\";\nimport \"./ud60x18/Conversions.sol\";\nimport \"./ud60x18/Errors.sol\";\nimport \"./ud60x18/Helpers.sol\";\nimport \"./ud60x18/Math.sol\";\nimport \"./ud60x18/ValueType.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "lib/rain.math.fixedpoint/src/lib/LibWillOverflow.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport \"./FixedPointDecimalConstants.sol\";\n\n/// @title LibWillOverflow\n/// @notice Often we want to know if some calculation is expected to overflow.\n/// Notably this is important for fuzzing as we have to be able to set\n/// expectations for arbitrary inputs over as broad a range of values as\n/// possible.\nlibrary LibWillOverflow {\n    /// Relevant logic taken direct from Open Zeppelin.\n    /// @param x As per Open Zeppelin.\n    /// @param y As per Open Zeppelin.\n    /// @param denominator As per Open Zeppelin.\n    /// @return True if mulDiv will overflow.\n    function mulDivWillOverflow(uint256 x, uint256 y, uint256 denominator) internal pure returns (bool) {\n        // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n        // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = prod1 * 2^256 + prod0.\n        uint256 prod0; // Least significant 256 bits of the product\n        uint256 prod1; // Most significant 256 bits of the product\n        assembly (\"memory-safe\") {\n            let mm := mulmod(x, y, not(0))\n            prod0 := mul(x, y)\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n        }\n        return !(denominator > prod1);\n    }\n\n    /// True if `scaleUp` will overflow.\n    /// @param a The number to scale up.\n    /// @param scaleBy The number of orders of magnitude to scale up by.\n    /// @return True if `scaleUp` will overflow.\n    function scaleUpWillOverflow(uint256 a, uint256 scaleBy) internal pure returns (bool) {\n        unchecked {\n            if (a == 0) {\n                return false;\n            }\n            if (scaleBy >= OVERFLOW_RESCALE_OOMS) {\n                return true;\n            }\n            uint256 b = 10 ** scaleBy;\n            uint256 c = a * b;\n            return c / b != a;\n        }\n    }\n\n    /// True if `scaleDown` will round.\n    /// @param a The number to scale down.\n    /// @param scaleDownBy The number of orders of magnitude to scale down by.\n    /// @return True if `scaleDown` will round.\n    function scaleDownWillRound(uint256 a, uint256 scaleDownBy) internal pure returns (bool) {\n        if (scaleDownBy >= OVERFLOW_RESCALE_OOMS) {\n            return a != 0;\n        }\n        uint256 b = 10 ** scaleDownBy;\n        uint256 c = a / b;\n        // Discovering precision loss is the whole point of this check so the\n        // thing slither is complaining about is exactly what we're measuring.\n        //slither-disable-next-line divide-before-multiply\n        return c * b != a;\n    }\n\n    /// True if `scale18` will overflow.\n    /// @param a The number to scale.\n    /// @param decimals The current number of decimals of `a`.\n    /// @param flags The flags to use.\n    /// @return True if `scale18` will overflow.\n    function scale18WillOverflow(uint256 a, uint256 decimals, uint256 flags) internal pure returns (bool) {\n        if (decimals < FIXED_POINT_DECIMALS && (FLAG_SATURATE & flags == 0)) {\n            return scaleUpWillOverflow(a, FIXED_POINT_DECIMALS - decimals);\n        } else {\n            return false;\n        }\n    }\n\n    /// True if `scaleN` will overflow.\n    /// @param a The number to scale.\n    /// @param decimals The current number of decimals of `a`.\n    /// @param flags The flags to use.\n    /// @return True if `scaleN` will overflow.\n    function scaleNWillOverflow(uint256 a, uint256 decimals, uint256 flags) internal pure returns (bool) {\n        if (decimals > FIXED_POINT_DECIMALS && (FLAG_SATURATE & flags == 0)) {\n            return scaleUpWillOverflow(a, decimals - FIXED_POINT_DECIMALS);\n        } else {\n            return false;\n        }\n    }\n\n    /// True if `scaleBy` will overflow.\n    /// @param a The number to scale.\n    /// @param scaleBy The number of orders of magnitude to scale by.\n    /// @param flags The flags to use.\n    /// @return True if `scaleBy` will overflow.\n    function scaleByWillOverflow(uint256 a, int8 scaleBy, uint256 flags) internal pure returns (bool) {\n        // If we're scaling up and not saturating check the overflow.\n        if (scaleBy > 0 && (FLAG_SATURATE & flags == 0)) {\n            return scaleUpWillOverflow(a, uint8(scaleBy));\n        } else {\n            return false;\n        }\n    }\n}\n"
      },
      "lib/rain.math.fixedpoint/src/lib/LibFixedPointDecimalScale.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport \"./FixedPointDecimalConstants.sol\";\n\n/// @title FixedPointDecimalScale\n/// @notice Tools to scale unsigned values to/from 18 decimal fixed point\n/// representation.\n///\n/// Overflows error and underflows are rounded up or down explicitly.\n///\n/// The max uint256 as decimal is roughly 1e77 so scaling values comparable to\n/// 1e18 is unlikely to ever overflow in most contexts. For a typical use case\n/// involving tokens, the entire supply of a token rescaled up a full 18 decimals\n/// would still put it \"only\" in the region of ~1e40 which has a full 30 orders\n/// of magnitude buffer before running into saturation issues. However, there's\n/// no theoretical reason that a token or any other use case couldn't use large\n/// numbers or extremely precise decimals that would push this library to\n/// overflow point, so it MUST be treated with caution around the edge cases.\n///\n/// Scaling down ANY fixed point decimal also reduces the precision which can\n/// lead to  dust or in the worst case trapped funds if subsequent subtraction\n/// overflows a rounded-down number. Consider using saturating subtraction for\n/// safety against previously downscaled values, and whether trapped dust is a\n/// significant issue. If you need to retain full/arbitrary precision in the case\n/// of downscaling DO NOT use this library.\n///\n/// All rescaling and/or division operations in this library require a rounding\n/// flag. This allows and forces the caller to specify where dust sits due to\n/// rounding. For example the caller could round up when taking tokens from\n/// `msg.sender` and round down when returning them, ensuring that any dust in\n/// the round trip accumulates in the contract rather than opening an exploit or\n/// reverting and trapping all funds. This is exactly how the ERC4626 vault spec\n/// handles dust and is a good reference point in general. Typically the contract\n/// holding tokens and non-interactive participants should be favoured by\n/// rounding calculations rather than active participants. This is because we\n/// assume that an active participant, e.g. `msg.sender`, knowns something we\n/// don't and is carefully crafting an attack, so we are most conservative and\n/// suspicious of their inputs and actions.\nlibrary LibFixedPointDecimalScale {\n    /// Scales `a` up by a specified number of decimals.\n    /// @param a The number to scale up.\n    /// @param scaleUpBy Number of orders of magnitude to scale `b_` up by.\n    /// Errors if overflows.\n    /// @return b `a` scaled up by `scaleUpBy`.\n    function scaleUp(uint256 a, uint256 scaleUpBy) internal pure returns (uint256 b) {\n        // Checked power is expensive so don't do that.\n        unchecked {\n            b = 10 ** scaleUpBy;\n        }\n        b = a * b;\n\n        // We know exactly when 10 ** X overflows so replay the checked version\n        // to get the standard Solidity overflow behaviour. The branching logic\n        // here is still ~230 gas cheaper than unconditionally running the\n        // overflow checks. We're optimising for standardisation rather than gas\n        // in the unhappy revert case.\n        if (scaleUpBy >= OVERFLOW_RESCALE_OOMS) {\n            b = a == 0 ? 0 : 10 ** scaleUpBy;\n        }\n    }\n\n    /// Identical to `scaleUp` but saturates instead of reverting on overflow.\n    /// @param a As per `scaleUp`.\n    /// @param scaleUpBy As per `scaleUp`.\n    /// @return c As per `scaleUp` but saturates as `type(uint256).max` on\n    /// overflow.\n    function scaleUpSaturating(uint256 a, uint256 scaleUpBy) internal pure returns (uint256 c) {\n        unchecked {\n            if (scaleUpBy >= OVERFLOW_RESCALE_OOMS) {\n                c = a == 0 ? 0 : type(uint256).max;\n            } else {\n                // Adapted from saturatingMath.\n                // Inlining everything here saves ~250-300+ gas relative to slow.\n                uint256 b_ = 10 ** scaleUpBy;\n                c = a * b_;\n                // Checking b_ here allows us to skip an \"is zero\" check because even\n                // 10 ** 0 = 1, so we have a positive lower bound on b_.\n                c = c / b_ == a ? c : type(uint256).max;\n            }\n        }\n    }\n\n    /// Scales `a` down by a specified number of decimals, rounding down.\n    /// Used internally by several other functions in this lib.\n    /// @param a The number to scale down.\n    /// @param scaleDownBy Number of orders of magnitude to scale `a` down by.\n    /// Overflows if greater than 77.\n    /// @return c `a` scaled down by `scaleDownBy` and rounded down.\n    function scaleDown(uint256 a, uint256 scaleDownBy) internal pure returns (uint256) {\n        unchecked {\n            return scaleDownBy >= OVERFLOW_RESCALE_OOMS ? 0 : a / (10 ** scaleDownBy);\n        }\n    }\n\n    /// Scales `a` down by a specified number of decimals, rounding up.\n    /// Used internally by several other functions in this lib.\n    /// @param a The number to scale down.\n    /// @param scaleDownBy Number of orders of magnitude to scale `a` down by.\n    /// Overflows if greater than 77.\n    /// @return c `a` scaled down by `scaleDownBy` and rounded up.\n    function scaleDownRoundUp(uint256 a, uint256 scaleDownBy) internal pure returns (uint256 c) {\n        unchecked {\n            if (scaleDownBy >= OVERFLOW_RESCALE_OOMS) {\n                c = a == 0 ? 0 : 1;\n            } else {\n                uint256 b = 10 ** scaleDownBy;\n                c = a / b;\n\n                // Intentionally doing a divide before multiply here to detect\n                // the need to round up.\n                //slither-disable-next-line divide-before-multiply\n                if (a != c * b) {\n                    c += 1;\n                }\n            }\n        }\n    }\n\n    /// Scale a fixed point decimal of some scale factor to 18 decimals.\n    /// @param a Some fixed point decimal value.\n    /// @param decimals The number of fixed decimals of `a`.\n    /// @param flags Controls rounding and saturation.\n    /// @return `a` scaled to 18 decimals.\n    function scale18(uint256 a, uint256 decimals, uint256 flags) internal pure returns (uint256) {\n        unchecked {\n            if (FIXED_POINT_DECIMALS > decimals) {\n                uint256 scaleUpBy = FIXED_POINT_DECIMALS - decimals;\n                if (flags & FLAG_SATURATE > 0) {\n                    return scaleUpSaturating(a, scaleUpBy);\n                } else {\n                    return scaleUp(a, scaleUpBy);\n                }\n            } else if (decimals > FIXED_POINT_DECIMALS) {\n                uint256 scaleDownBy = decimals - FIXED_POINT_DECIMALS;\n                if (flags & FLAG_ROUND_UP > 0) {\n                    return scaleDownRoundUp(a, scaleDownBy);\n                } else {\n                    return scaleDown(a, scaleDownBy);\n                }\n            } else {\n                return a;\n            }\n        }\n    }\n\n    /// Scale an 18 decimal fixed point value to some other scale.\n    /// Exactly the inverse behaviour of `scale18`. Where `scale18` would scale\n    /// up, `scaleN` scales down, and vice versa.\n    /// @param a An 18 decimal fixed point number.\n    /// @param targetDecimals The new scale of `a`.\n    /// @param flags Controls rounding and saturation.\n    /// @return `a` rescaled from 18 to `targetDecimals`.\n    function scaleN(uint256 a, uint256 targetDecimals, uint256 flags) internal pure returns (uint256) {\n        unchecked {\n            if (FIXED_POINT_DECIMALS > targetDecimals) {\n                uint256 scaleDownBy = FIXED_POINT_DECIMALS - targetDecimals;\n                if (flags & FLAG_ROUND_UP > 0) {\n                    return scaleDownRoundUp(a, scaleDownBy);\n                } else {\n                    return scaleDown(a, scaleDownBy);\n                }\n            } else if (targetDecimals > FIXED_POINT_DECIMALS) {\n                uint256 scaleUpBy = targetDecimals - FIXED_POINT_DECIMALS;\n                if (flags & FLAG_SATURATE > 0) {\n                    return scaleUpSaturating(a, scaleUpBy);\n                } else {\n                    return scaleUp(a, scaleUpBy);\n                }\n            } else {\n                return a;\n            }\n        }\n    }\n\n    /// Scale a fixed point up or down by `ooms` orders of magnitude.\n    /// Notably `scaleBy` is a SIGNED integer so scaling down by negative OOMS\n    /// IS supported.\n    /// @param a Some integer of any scale.\n    /// @param ooms OOMs to scale `a` up or down by. This is a SIGNED int8\n    /// which means it can be negative, and also means that sign extension MUST\n    /// be considered if changing it to another type.\n    /// @param flags Controls rounding and saturating.\n    /// @return `a` rescaled according to `ooms`.\n    function scaleBy(uint256 a, int8 ooms, uint256 flags) internal pure returns (uint256) {\n        unchecked {\n            if (ooms > 0) {\n                if (flags & FLAG_SATURATE > 0) {\n                    return scaleUpSaturating(a, uint8(ooms));\n                } else {\n                    return scaleUp(a, uint8(ooms));\n                }\n            } else if (ooms < 0) {\n                // We know that ooms is negative here, so we can convert it\n                // to an absolute value with bitwise NOT + 1.\n                // This is slightly less gas than multiplying by negative 1 and\n                // casting it, and handles the case of -128 without overflow.\n                uint8 scaleDownBy = uint8(~ooms) + 1;\n                if (flags & FLAG_ROUND_UP > 0) {\n                    return scaleDownRoundUp(a, scaleDownBy);\n                } else {\n                    return scaleDown(a, scaleDownBy);\n                }\n            } else {\n                return a;\n            }\n        }\n    }\n}\n"
      },
      "lib/sol.lib.binmaskflag/src/Binary.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev Binary 1.\nuint256 constant B_1 = 2 ** 1 - 1;\n/// @dev Binary 11.\nuint256 constant B_11 = 2 ** 2 - 1;\n/// @dev Binary 111.\nuint256 constant B_111 = 2 ** 3 - 1;\n/// @dev Binary 1111.\nuint256 constant B_1111 = 2 ** 4 - 1;\n/// @dev Binary 11111.\nuint256 constant B_11111 = 2 ** 5 - 1;\n/// @dev Binary 111111.\nuint256 constant B_111111 = 2 ** 6 - 1;\n/// @dev Binary 1111111.\nuint256 constant B_1111111 = 2 ** 7 - 1;\n/// @dev Binary 11111111.\nuint256 constant B_11111111 = 2 ** 8 - 1;\n/// @dev Binary 111111111.\nuint256 constant B_111111111 = 2 ** 9 - 1;\n/// @dev Binary 1111111111.\nuint256 constant B_1111111111 = 2 ** 10 - 1;\n/// @dev Binary 11111111111.\nuint256 constant B_11111111111 = 2 ** 11 - 1;\n/// @dev Binary 111111111111.\nuint256 constant B_111111111111 = 2 ** 12 - 1;\n/// @dev Binary 1111111111111.\nuint256 constant B_1111111111111 = 2 ** 13 - 1;\n/// @dev Binary 11111111111111.\nuint256 constant B_11111111111111 = 2 ** 14 - 1;\n/// @dev Binary 111111111111111.\nuint256 constant B_111111111111111 = 2 ** 15 - 1;\n/// @dev Binary 1111111111111111.\nuint256 constant B_1111111111111111 = 2 ** 16 - 1;\n\n/// @dev Bitmask for 1 bit.\nuint256 constant MASK_1BIT = B_1;\n/// @dev Bitmask for 2 bits.\nuint256 constant MASK_2BIT = B_11;\n/// @dev Bitmask for 3 bits.\nuint256 constant MASK_3BIT = B_111;\n/// @dev Bitmask for 4 bits.\nuint256 constant MASK_4BIT = B_1111;\n/// @dev Bitmask for 5 bits.\nuint256 constant MASK_5BIT = B_11111;\n/// @dev Bitmask for 6 bits.\nuint256 constant MASK_6BIT = B_111111;\n/// @dev Bitmask for 7 bits.\nuint256 constant MASK_7BIT = B_1111111;\n/// @dev Bitmask for 8 bits.\nuint256 constant MASK_8BIT = B_11111111;\n/// @dev Bitmask for 9 bits.\nuint256 constant MASK_9BIT = B_111111111;\n/// @dev Bitmask for 10 bits.\nuint256 constant MASK_10BIT = B_1111111111;\n/// @dev Bitmask for 11 bits.\nuint256 constant MASK_11BIT = B_11111111111;\n/// @dev Bitmask for 12 bits.\nuint256 constant MASK_12BIT = B_111111111111;\n/// @dev Bitmask for 13 bits.\nuint256 constant MASK_13BIT = B_1111111111111;\n/// @dev Bitmask for 14 bits.\nuint256 constant MASK_14BIT = B_11111111111111;\n/// @dev Bitmask for 15 bits.\nuint256 constant MASK_15BIT = B_111111111111111;\n/// @dev Bitmask for 16 bits.\nuint256 constant MASK_16BIT = B_1111111111111111;\n"
      },
      "lib/rain.math.saturating/src/SaturatingMath.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @title SaturatingMath\n/// @notice Sometimes we neither want math operations to error nor wrap around\n/// on an overflow or underflow. In the case of transferring assets an error\n/// may cause assets to be locked in an irretrievable state within the erroring\n/// contract, e.g. due to a tiny rounding/calculation error. We also can't have\n/// assets underflowing and attempting to approve/transfer \"infinity\" when we\n/// wanted \"almost or exactly zero\" but some calculation bug underflowed zero.\n/// Ideally there are no calculation mistakes, but in guarding against bugs it\n/// may be safer pragmatically to saturate arithmatic at the numeric bounds.\n/// Note that saturating div is not supported because 0/0 is undefined.\nlibrary SaturatingMath {\n    /// Saturating addition.\n    /// @param a_ First term.\n    /// @param b_ Second term.\n    /// @return Minimum of a_ + b_ and max uint256.\n    function saturatingAdd(uint256 a_, uint256 b_) internal pure returns (uint256) {\n        unchecked {\n            uint256 c_ = a_ + b_;\n            return c_ < a_ ? type(uint256).max : c_;\n        }\n    }\n\n    /// Saturating subtraction.\n    /// @param a_ Minuend.\n    /// @param b_ Subtrahend.\n    /// @return Maximum of a_ - b_ and 0.\n    function saturatingSub(uint256 a_, uint256 b_) internal pure returns (uint256) {\n        unchecked {\n            return a_ > b_ ? a_ - b_ : 0;\n        }\n    }\n\n    /// Saturating multiplication.\n    /// @param a_ First term.\n    /// @param b_ Second term.\n    /// @return Minimum of a_ * b_ and max uint256.\n    function saturatingMul(uint256 a_, uint256 b_) internal pure returns (uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being\n            // zero, but the benefit is lost if 'b' is also tested.\n            // https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a_ == 0) return 0;\n            uint256 c_ = a_ * b_;\n            return c_ / a_ != b_ ? type(uint256).max : c_;\n        }\n    }\n}\n"
      },
      "lib/rain.interpreter.interface/src/interface/deprecated/IInterpreterStoreV1.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {StateNamespace} from \"./IInterpreterV1.sol\";\n\n/// A fully qualified namespace includes the interpreter's own namespacing logic\n/// IN ADDITION to the calling contract's requested `StateNamespace`. Typically\n/// this involves hashing the `msg.sender` into the `StateNamespace` so that each\n/// caller operates within its own disjoint state universe. Intepreters MUST NOT\n/// allow either the caller nor any expression/word to modify this directly on\n/// pain of potential key collisions on writes to the interpreter's own storage.\ntype FullyQualifiedNamespace is uint256;\n\nIInterpreterStoreV1 constant NO_STORE = IInterpreterStoreV1(address(0));\n\n/// @title IInterpreterStoreV1\n/// @notice Tracks state changes on behalf of an interpreter. A single store can\n/// handle state changes for many calling contracts, many interpreters and many\n/// expressions. The store is responsible for ensuring that applying these state\n/// changes is safe from key collisions with calls to `set` from different\n/// `msg.sender` callers. I.e. it MUST NOT be possible for a caller to modify the\n/// state changes associated with some other caller.\n///\n/// The store defines the shape of its own state changes, which is opaque to the\n/// calling contract. For example, some store may treat the list of state changes\n/// as a pairwise key/value set, and some other store may treat it as a literal\n/// list to be stored as-is.\n///\n/// Each interpreter decides for itself which store to use based on the\n/// compatibility of its own opcodes.\n///\n/// The store MUST assume the state changes have been corrupted by the calling\n/// contract due to bugs or malicious intent, and enforce state isolation between\n/// callers despite arbitrarily invalid state changes. The store MUST revert if\n/// it can detect invalid state changes, such as a key/value list having an odd\n/// number of items, but this MAY NOT be possible if the corruption is\n/// undetectable.\ninterface IInterpreterStoreV1 {\n    /// Mutates the interpreter store in bulk. The bulk values are provided in\n    /// the form of a `uint256[]` which can be treated e.g. as pairwise keys and\n    /// values to be stored in a Solidity mapping. The `IInterpreterStoreV1`\n    /// defines the meaning of the `uint256[]` for its own storage logic.\n    ///\n    /// @param namespace The unqualified namespace for the set that MUST be\n    /// fully qualified by the `IInterpreterStoreV1` to prevent key collisions\n    /// between callers. The fully qualified namespace forms a compound key with\n    /// the keys for each value to set.\n    /// @param kvs The list of changes to apply to the store's internal state.\n    function set(StateNamespace namespace, uint256[] calldata kvs) external;\n\n    /// Given a fully qualified namespace and key, return the associated value.\n    /// Ostensibly the interpreter can use this to implement opcodes that read\n    /// previously set values. The interpreter MUST apply the same qualification\n    /// logic as the store that it uses to guarantee consistent round tripping of\n    /// data and prevent malicious behaviours. Technically also allows onchain\n    /// reads of any set value from any contract, not just interpreters, but in\n    /// this case readers MUST be aware and handle inconsistencies between get\n    /// and set while the state changes are still in memory in the calling\n    /// context and haven't yet been persisted to the store.\n    ///\n    /// `IInterpreterStoreV1` uses the same fallback behaviour for unset keys as\n    /// Solidity. Specifically, any UNSET VALUES SILENTLY FALLBACK TO `0`.\n    /// @param namespace The fully qualified namespace to get a single value for.\n    /// @param key The key to get the value for within the namespace.\n    /// @return The value OR ZERO IF NOT SET.\n    function get(FullyQualifiedNamespace namespace, uint256 key) external view returns (uint256);\n}\n"
      },
      "lib/rain.interpreter.interface/src/error/ErrBytecode.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.19;\n\n/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572\ncontract ErrBytecode {}\n\n/// Thrown when a bytecode source index is out of bounds.\n/// @param bytecode The bytecode that was inspected.\n/// @param sourceIndex The source index that was out of bounds.\nerror SourceIndexOutOfBounds(bytes bytecode, uint256 sourceIndex);\n\n/// Thrown when a bytecode reports itself as 0 sources but has more than 1 byte.\n/// @param bytecode The bytecode that was inspected.\nerror UnexpectedSources(bytes bytecode);\n\n/// Thrown when bytes are discovered between the offsets and the sources.\n/// @param bytecode The bytecode that was inspected.\nerror UnexpectedTrailingOffsetBytes(bytes bytecode);\n\n/// Thrown when the end of a source as self reported by its header doesnt match\n/// the start of the next source or the end of the bytecode.\n/// @param bytecode The bytecode that was inspected.\nerror TruncatedSource(bytes bytecode);\n\n/// Thrown when the offset to a source points to a location that cannot fit a\n/// header before the start of the next source or the end of the bytecode.\n/// @param bytecode The bytecode that was inspected.\nerror TruncatedHeader(bytes bytecode);\n\n/// Thrown when the bytecode is truncated before the end of the header offsets.\n/// @param bytecode The bytecode that was inspected.\nerror TruncatedHeaderOffsets(bytes bytecode);\n\n/// Thrown when the stack sizings, allocation, inputs and outputs, are not\n/// monotonically increasing.\n/// @param bytecode The bytecode that was inspected.\n/// @param relativeOffset The relative offset of the source that was inspected.\nerror StackSizingsNotMonotonic(bytes bytecode, uint256 relativeOffset);\n"
      },
      "lib/rain.interpreter.interface/src/interface/deprecated/IInterpreterExternV2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {EncodedExternDispatch, ExternDispatch} from \"./IInterpreterExternV1.sol\";\n\n/// @title IInterpreterExternV2\n/// Handle a single dispatch from some calling contract with an array of\n/// inputs and array of outputs. Ostensibly useful to build \"word packs\" for\n/// `IInterpreterV1` so that less frequently used words can be provided in\n/// a less efficient format, but without bloating the base interpreter in\n/// terms of code size. Effectively allows unlimited words to exist as externs\n/// alongside interpreters.\n///\n/// The only difference between V2 and V1 is that V2 allows for the inputs and\n/// outputs to be in calldata rather than memory.\ninterface IInterpreterExternV2 {\n    /// Handles a single dispatch.\n    /// @param dispatch Encoded information about the extern to dispatch.\n    /// Analogous to the opcode/operand in the interpreter.\n    /// @param inputs The array of inputs for the dispatched logic.\n    /// @return outputs The result of the dispatched logic.\n    function extern(ExternDispatch dispatch, uint256[] calldata inputs)\n        external\n        view\n        returns (uint256[] calldata outputs);\n}\n"
      },
      "lib/prb-math/src/ud60x18/Casting.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Errors.sol\" as CastingErrors;\nimport { MAX_UINT128, MAX_UINT40 } from \"../Common.sol\";\nimport { uMAX_SD1x18 } from \"../sd1x18/Constants.sol\";\nimport { SD1x18 } from \"../sd1x18/ValueType.sol\";\nimport { uMAX_SD59x18 } from \"../sd59x18/Constants.sol\";\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { uMAX_UD2x18 } from \"../ud2x18/Constants.sol\";\nimport { UD2x18 } from \"../ud2x18/ValueType.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Casts a UD60x18 number into SD1x18.\n/// @dev Requirements:\n/// - x must be less than or equal to `uMAX_SD1x18`.\nfunction intoSD1x18(UD60x18 x) pure returns (SD1x18 result) {\n    uint256 xUint = UD60x18.unwrap(x);\n    if (xUint > uint256(int256(uMAX_SD1x18))) {\n        revert CastingErrors.PRBMath_UD60x18_IntoSD1x18_Overflow(x);\n    }\n    result = SD1x18.wrap(int64(uint64(xUint)));\n}\n\n/// @notice Casts a UD60x18 number into UD2x18.\n/// @dev Requirements:\n/// - x must be less than or equal to `uMAX_UD2x18`.\nfunction intoUD2x18(UD60x18 x) pure returns (UD2x18 result) {\n    uint256 xUint = UD60x18.unwrap(x);\n    if (xUint > uMAX_UD2x18) {\n        revert CastingErrors.PRBMath_UD60x18_IntoUD2x18_Overflow(x);\n    }\n    result = UD2x18.wrap(uint64(xUint));\n}\n\n/// @notice Casts a UD60x18 number into SD59x18.\n/// @dev Requirements:\n/// - x must be less than or equal to `uMAX_SD59x18`.\nfunction intoSD59x18(UD60x18 x) pure returns (SD59x18 result) {\n    uint256 xUint = UD60x18.unwrap(x);\n    if (xUint > uint256(uMAX_SD59x18)) {\n        revert CastingErrors.PRBMath_UD60x18_IntoSD59x18_Overflow(x);\n    }\n    result = SD59x18.wrap(int256(xUint));\n}\n\n/// @notice Casts a UD60x18 number into uint128.\n/// @dev This is basically an alias for {unwrap}.\nfunction intoUint256(UD60x18 x) pure returns (uint256 result) {\n    result = UD60x18.unwrap(x);\n}\n\n/// @notice Casts a UD60x18 number into uint128.\n/// @dev Requirements:\n/// - x must be less than or equal to `MAX_UINT128`.\nfunction intoUint128(UD60x18 x) pure returns (uint128 result) {\n    uint256 xUint = UD60x18.unwrap(x);\n    if (xUint > MAX_UINT128) {\n        revert CastingErrors.PRBMath_UD60x18_IntoUint128_Overflow(x);\n    }\n    result = uint128(xUint);\n}\n\n/// @notice Casts a UD60x18 number into uint40.\n/// @dev Requirements:\n/// - x must be less than or equal to `MAX_UINT40`.\nfunction intoUint40(UD60x18 x) pure returns (uint40 result) {\n    uint256 xUint = UD60x18.unwrap(x);\n    if (xUint > MAX_UINT40) {\n        revert CastingErrors.PRBMath_UD60x18_IntoUint40_Overflow(x);\n    }\n    result = uint40(xUint);\n}\n\n/// @notice Alias for {wrap}.\nfunction ud(uint256 x) pure returns (UD60x18 result) {\n    result = UD60x18.wrap(x);\n}\n\n/// @notice Alias for {wrap}.\nfunction ud60x18(uint256 x) pure returns (UD60x18 result) {\n    result = UD60x18.wrap(x);\n}\n\n/// @notice Unwraps a UD60x18 number into uint256.\nfunction unwrap(UD60x18 x) pure returns (uint256 result) {\n    result = UD60x18.unwrap(x);\n}\n\n/// @notice Wraps a uint256 number into the UD60x18 value type.\nfunction wrap(uint256 x) pure returns (UD60x18 result) {\n    result = UD60x18.wrap(x);\n}\n"
      },
      "lib/prb-math/src/ud60x18/Constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD60x18 } from \"./ValueType.sol\";\n\n// NOTICE: the \"u\" prefix stands for \"unwrapped\".\n\n/// @dev Euler's number as a UD60x18 number.\nUD60x18 constant E = UD60x18.wrap(2_718281828459045235);\n\n/// @dev The maximum input permitted in {exp}.\nuint256 constant uEXP_MAX_INPUT = 133_084258667509499440;\nUD60x18 constant EXP_MAX_INPUT = UD60x18.wrap(uEXP_MAX_INPUT);\n\n/// @dev The maximum input permitted in {exp2}.\nuint256 constant uEXP2_MAX_INPUT = 192e18 - 1;\nUD60x18 constant EXP2_MAX_INPUT = UD60x18.wrap(uEXP2_MAX_INPUT);\n\n/// @dev Half the UNIT number.\nuint256 constant uHALF_UNIT = 0.5e18;\nUD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT);\n\n/// @dev $log_2(10)$ as a UD60x18 number.\nuint256 constant uLOG2_10 = 3_321928094887362347;\nUD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10);\n\n/// @dev $log_2(e)$ as a UD60x18 number.\nuint256 constant uLOG2_E = 1_442695040888963407;\nUD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E);\n\n/// @dev The maximum value a UD60x18 number can have.\nuint256 constant uMAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\nUD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18);\n\n/// @dev The maximum whole value a UD60x18 number can have.\nuint256 constant uMAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\nUD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18);\n\n/// @dev PI as a UD60x18 number.\nUD60x18 constant PI = UD60x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of UD60x18.\nuint256 constant uUNIT = 1e18;\nUD60x18 constant UNIT = UD60x18.wrap(uUNIT);\n\n/// @dev The unit number squared.\nuint256 constant uUNIT_SQUARED = 1e36;\nUD60x18 constant UNIT_SQUARED = UD60x18.wrap(uUNIT_SQUARED);\n\n/// @dev Zero as a UD60x18 number.\nUD60x18 constant ZERO = UD60x18.wrap(0);\n"
      },
      "lib/prb-math/src/ud60x18/Conversions.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { uMAX_UD60x18, uUNIT } from \"./Constants.sol\";\nimport { PRBMath_UD60x18_Convert_Overflow } from \"./Errors.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Converts a UD60x18 number to a simple integer by dividing it by `UNIT`.\n/// @dev The result is rounded toward zero.\n/// @param x The UD60x18 number to convert.\n/// @return result The same number in basic integer form.\nfunction convert(UD60x18 x) pure returns (uint256 result) {\n    result = UD60x18.unwrap(x) / uUNIT;\n}\n\n/// @notice Converts a simple integer to UD60x18 by multiplying it by `UNIT`.\n///\n/// @dev Requirements:\n/// - x must be less than or equal to `MAX_UD60x18 / UNIT`.\n///\n/// @param x The basic integer to convert.\n/// @param result The same number converted to UD60x18.\nfunction convert(uint256 x) pure returns (UD60x18 result) {\n    if (x > uMAX_UD60x18 / uUNIT) {\n        revert PRBMath_UD60x18_Convert_Overflow(x);\n    }\n    unchecked {\n        result = UD60x18.wrap(x * uUNIT);\n    }\n}\n"
      },
      "lib/prb-math/src/ud60x18/Errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when ceiling a number overflows UD60x18.\nerror PRBMath_UD60x18_Ceil_Overflow(UD60x18 x);\n\n/// @notice Thrown when converting a basic integer to the fixed-point format overflows UD60x18.\nerror PRBMath_UD60x18_Convert_Overflow(uint256 x);\n\n/// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441.\nerror PRBMath_UD60x18_Exp_InputTooBig(UD60x18 x);\n\n/// @notice Thrown when taking the binary exponent of a base greater than 192e18.\nerror PRBMath_UD60x18_Exp2_InputTooBig(UD60x18 x);\n\n/// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows UD60x18.\nerror PRBMath_UD60x18_Gm_Overflow(UD60x18 x, UD60x18 y);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18.\nerror PRBMath_UD60x18_IntoSD1x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD59x18.\nerror PRBMath_UD60x18_IntoSD59x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18.\nerror PRBMath_UD60x18_IntoUD2x18_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128.\nerror PRBMath_UD60x18_IntoUint128_Overflow(UD60x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40.\nerror PRBMath_UD60x18_IntoUint40_Overflow(UD60x18 x);\n\n/// @notice Thrown when taking the logarithm of a number less than 1.\nerror PRBMath_UD60x18_Log_InputTooSmall(UD60x18 x);\n\n/// @notice Thrown when calculating the square root overflows UD60x18.\nerror PRBMath_UD60x18_Sqrt_Overflow(UD60x18 x);\n"
      },
      "lib/prb-math/src/ud60x18/Helpers.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { wrap } from \"./Casting.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/// @notice Implements the checked addition operation (+) in the UD60x18 type.\nfunction add(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() + y.unwrap());\n}\n\n/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.\nfunction and(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() & bits);\n}\n\n/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.\nfunction and2(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() & y.unwrap());\n}\n\n/// @notice Implements the equal operation (==) in the UD60x18 type.\nfunction eq(UD60x18 x, UD60x18 y) pure returns (bool result) {\n    result = x.unwrap() == y.unwrap();\n}\n\n/// @notice Implements the greater than operation (>) in the UD60x18 type.\nfunction gt(UD60x18 x, UD60x18 y) pure returns (bool result) {\n    result = x.unwrap() > y.unwrap();\n}\n\n/// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type.\nfunction gte(UD60x18 x, UD60x18 y) pure returns (bool result) {\n    result = x.unwrap() >= y.unwrap();\n}\n\n/// @notice Implements a zero comparison check function in the UD60x18 type.\nfunction isZero(UD60x18 x) pure returns (bool result) {\n    // This wouldn't work if x could be negative.\n    result = x.unwrap() == 0;\n}\n\n/// @notice Implements the left shift operation (<<) in the UD60x18 type.\nfunction lshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() << bits);\n}\n\n/// @notice Implements the lower than operation (<) in the UD60x18 type.\nfunction lt(UD60x18 x, UD60x18 y) pure returns (bool result) {\n    result = x.unwrap() < y.unwrap();\n}\n\n/// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type.\nfunction lte(UD60x18 x, UD60x18 y) pure returns (bool result) {\n    result = x.unwrap() <= y.unwrap();\n}\n\n/// @notice Implements the checked modulo operation (%) in the UD60x18 type.\nfunction mod(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() % y.unwrap());\n}\n\n/// @notice Implements the not equal operation (!=) in the UD60x18 type.\nfunction neq(UD60x18 x, UD60x18 y) pure returns (bool result) {\n    result = x.unwrap() != y.unwrap();\n}\n\n/// @notice Implements the NOT (~) bitwise operation in the UD60x18 type.\nfunction not(UD60x18 x) pure returns (UD60x18 result) {\n    result = wrap(~x.unwrap());\n}\n\n/// @notice Implements the OR (|) bitwise operation in the UD60x18 type.\nfunction or(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() | y.unwrap());\n}\n\n/// @notice Implements the right shift operation (>>) in the UD60x18 type.\nfunction rshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() >> bits);\n}\n\n/// @notice Implements the checked subtraction operation (-) in the UD60x18 type.\nfunction sub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() - y.unwrap());\n}\n\n/// @notice Implements the unchecked addition operation (+) in the UD60x18 type.\nfunction uncheckedAdd(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    unchecked {\n        result = wrap(x.unwrap() + y.unwrap());\n    }\n}\n\n/// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type.\nfunction uncheckedSub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    unchecked {\n        result = wrap(x.unwrap() - y.unwrap());\n    }\n}\n\n/// @notice Implements the XOR (^) bitwise operation in the UD60x18 type.\nfunction xor(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(x.unwrap() ^ y.unwrap());\n}\n"
      },
      "lib/prb-math/src/ud60x18/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as Errors;\nimport { wrap } from \"./Casting.sol\";\nimport {\n    uEXP_MAX_INPUT,\n    uEXP2_MAX_INPUT,\n    uHALF_UNIT,\n    uLOG2_10,\n    uLOG2_E,\n    uMAX_UD60x18,\n    uMAX_WHOLE_UD60x18,\n    UNIT,\n    uUNIT,\n    uUNIT_SQUARED,\n    ZERO\n} from \"./Constants.sol\";\nimport { UD60x18 } from \"./ValueType.sol\";\n\n/*//////////////////////////////////////////////////////////////////////////\n                            MATHEMATICAL FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Calculates the arithmetic average of x and y using the following formula:\n///\n/// $$\n/// avg(x, y) = (x & y) + ((xUint ^ yUint) / 2)\n/// $$\n//\n/// In English, this is what this formula does:\n///\n/// 1. AND x and y.\n/// 2. Calculate half of XOR x and y.\n/// 3. Add the two results together.\n///\n/// This technique is known as SWAR, which stands for \"SIMD within a register\". You can read more about it here:\n/// https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// @param x The first operand as a UD60x18 number.\n/// @param y The second operand as a UD60x18 number.\n/// @return result The arithmetic average as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction avg(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n    uint256 yUint = y.unwrap();\n    unchecked {\n        result = wrap((xUint & yUint) + ((xUint ^ yUint) >> 1));\n    }\n}\n\n/// @notice Yields the smallest whole number greater than or equal to x.\n///\n/// @dev This is optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional\n/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n///\n/// Requirements:\n/// - x must be less than or equal to `MAX_WHOLE_UD60x18`.\n///\n/// @param x The UD60x18 number to ceil.\n/// @param result The smallest whole number greater than or equal to x, as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ceil(UD60x18 x) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n    if (xUint > uMAX_WHOLE_UD60x18) {\n        revert Errors.PRBMath_UD60x18_Ceil_Overflow(x);\n    }\n\n    assembly (\"memory-safe\") {\n        // Equivalent to `x % UNIT`.\n        let remainder := mod(x, uUNIT)\n\n        // Equivalent to `UNIT - remainder`.\n        let delta := sub(uUNIT, remainder)\n\n        // Equivalent to `x + remainder > 0 ? delta : 0`.\n        result := add(x, mul(delta, gt(remainder, 0)))\n    }\n}\n\n/// @notice Divides two UD60x18 numbers, returning a new UD60x18 number.\n///\n/// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv}.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv}.\n///\n/// @param x The numerator as a UD60x18 number.\n/// @param y The denominator as a UD60x18 number.\n/// @param result The quotient as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction div(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(Common.mulDiv(x.unwrap(), uUNIT, y.unwrap()));\n}\n\n/// @notice Calculates the natural exponent of x using the following formula:\n///\n/// $$\n/// e^x = 2^{x * log_2{e}}\n/// $$\n///\n/// @dev Requirements:\n/// - x must be less than 133_084258667509499441.\n///\n/// @param x The exponent as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp(UD60x18 x) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n\n    // This check prevents values greater than 192e18 from being passed to {exp2}.\n    if (xUint > uEXP_MAX_INPUT) {\n        revert Errors.PRBMath_UD60x18_Exp_InputTooBig(x);\n    }\n\n    unchecked {\n        // Inline the fixed-point multiplication to save gas.\n        uint256 doubleUnitProduct = xUint * uLOG2_E;\n        result = exp2(wrap(doubleUnitProduct / uUNIT));\n    }\n}\n\n/// @notice Calculates the binary exponent of x using the binary fraction method.\n///\n/// @dev See https://ethereum.stackexchange.com/q/79903/24693\n///\n/// Requirements:\n/// - x must be less than 192e18.\n/// - The result must fit in UD60x18.\n///\n/// @param x The exponent as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp2(UD60x18 x) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n\n    // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format.\n    if (xUint > uEXP2_MAX_INPUT) {\n        revert Errors.PRBMath_UD60x18_Exp2_InputTooBig(x);\n    }\n\n    // Convert x to the 192.64-bit fixed-point format.\n    uint256 x_192x64 = (xUint << 64) / uUNIT;\n\n    // Pass x to the {Common.exp2} function, which uses the 192.64-bit fixed-point number representation.\n    result = wrap(Common.exp2(x_192x64));\n}\n\n/// @notice Yields the greatest whole number less than or equal to x.\n/// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts.\n/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n/// @param x The UD60x18 number to floor.\n/// @param result The greatest whole number less than or equal to x, as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction floor(UD60x18 x) pure returns (UD60x18 result) {\n    assembly (\"memory-safe\") {\n        // Equivalent to `x % UNIT`.\n        let remainder := mod(x, uUNIT)\n\n        // Equivalent to `x - remainder > 0 ? remainder : 0)`.\n        result := sub(x, mul(remainder, gt(remainder, 0)))\n    }\n}\n\n/// @notice Yields the excess beyond the floor of x using the odd function definition.\n/// @dev See https://en.wikipedia.org/wiki/Fractional_part.\n/// @param x The UD60x18 number to get the fractional part of.\n/// @param result The fractional part of x as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction frac(UD60x18 x) pure returns (UD60x18 result) {\n    assembly (\"memory-safe\") {\n        result := mod(x, uUNIT)\n    }\n}\n\n/// @notice Calculates the geometric mean of x and y, i.e. $\\sqrt{x * y}$, rounding down.\n///\n/// @dev Requirements:\n/// - x * y must fit in UD60x18.\n///\n/// @param x The first operand as a UD60x18 number.\n/// @param y The second operand as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction gm(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n    uint256 yUint = y.unwrap();\n    if (xUint == 0 || yUint == 0) {\n        return ZERO;\n    }\n\n    unchecked {\n        // Checking for overflow this way is faster than letting Solidity do it.\n        uint256 xyUint = xUint * yUint;\n        if (xyUint / xUint != yUint) {\n            revert Errors.PRBMath_UD60x18_Gm_Overflow(x, y);\n        }\n\n        // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT`\n        // during multiplication. See the comments in {Common.sqrt}.\n        result = wrap(Common.sqrt(xyUint));\n    }\n}\n\n/// @notice Calculates the inverse of x.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x must not be zero.\n///\n/// @param x The UD60x18 number for which to calculate the inverse.\n/// @return result The inverse as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction inv(UD60x18 x) pure returns (UD60x18 result) {\n    unchecked {\n        result = wrap(uUNIT_SQUARED / x.unwrap());\n    }\n}\n\n/// @notice Calculates the natural logarithm of x using the following formula:\n///\n/// $$\n/// ln{x} = log_2{x} / log_2{e}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n/// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The UD60x18 number for which to calculate the natural logarithm.\n/// @return result The natural logarithm as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ln(UD60x18 x) pure returns (UD60x18 result) {\n    unchecked {\n        // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that\n        // {log2} can return is ~196_205294292027477728.\n        result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E);\n    }\n}\n\n/// @notice Calculates the common logarithm of x using the following formula:\n///\n/// $$\n/// log_{10}{x} = log_2{x} / log_2{10}\n/// $$\n///\n/// However, if x is an exact power of ten, a hard coded value is returned.\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The UD60x18 number for which to calculate the common logarithm.\n/// @return result The common logarithm as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log10(UD60x18 x) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n    if (xUint < uUNIT) {\n        revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x);\n    }\n\n    // Note that the `mul` in this assembly block is the standard multiplication operation, not {UD60x18.mul}.\n    // prettier-ignore\n    assembly (\"memory-safe\") {\n        switch x\n        case 1 { result := mul(uUNIT, sub(0, 18)) }\n        case 10 { result := mul(uUNIT, sub(1, 18)) }\n        case 100 { result := mul(uUNIT, sub(2, 18)) }\n        case 1000 { result := mul(uUNIT, sub(3, 18)) }\n        case 10000 { result := mul(uUNIT, sub(4, 18)) }\n        case 100000 { result := mul(uUNIT, sub(5, 18)) }\n        case 1000000 { result := mul(uUNIT, sub(6, 18)) }\n        case 10000000 { result := mul(uUNIT, sub(7, 18)) }\n        case 100000000 { result := mul(uUNIT, sub(8, 18)) }\n        case 1000000000 { result := mul(uUNIT, sub(9, 18)) }\n        case 10000000000 { result := mul(uUNIT, sub(10, 18)) }\n        case 100000000000 { result := mul(uUNIT, sub(11, 18)) }\n        case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }\n        case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }\n        case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }\n        case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }\n        case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }\n        case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }\n        case 1000000000000000000 { result := 0 }\n        case 10000000000000000000 { result := uUNIT }\n        case 100000000000000000000 { result := mul(uUNIT, 2) }\n        case 1000000000000000000000 { result := mul(uUNIT, 3) }\n        case 10000000000000000000000 { result := mul(uUNIT, 4) }\n        case 100000000000000000000000 { result := mul(uUNIT, 5) }\n        case 1000000000000000000000000 { result := mul(uUNIT, 6) }\n        case 10000000000000000000000000 { result := mul(uUNIT, 7) }\n        case 100000000000000000000000000 { result := mul(uUNIT, 8) }\n        case 1000000000000000000000000000 { result := mul(uUNIT, 9) }\n        case 10000000000000000000000000000 { result := mul(uUNIT, 10) }\n        case 100000000000000000000000000000 { result := mul(uUNIT, 11) }\n        case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }\n        case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }\n        case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }\n        case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }\n        case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }\n        case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }\n        case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }\n        case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }\n        case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }\n        case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }\n        case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }\n        case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }\n        case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }\n        case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }\n        case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }\n        case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }\n        case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }\n        case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }\n        case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }\n        case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }\n        case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }\n        case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }\n        case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }\n        case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }\n        case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }\n        case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }\n        case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }\n        case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }\n        case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }\n        case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }\n        case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }\n        case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }\n        case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }\n        case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }\n        case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }\n        case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }\n        case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }\n        case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }\n        case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }\n        case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 59) }\n        default { result := uMAX_UD60x18 }\n    }\n\n    if (result.unwrap() == uMAX_UD60x18) {\n        unchecked {\n            // Inline the fixed-point division to save gas.\n            result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10);\n        }\n    }\n}\n\n/// @notice Calculates the binary logarithm of x using the iterative approximation algorithm:\n///\n/// $$\n/// log_2{x} = n + log_2{y}, \\text{ where } y = x*2^{-n}, \\ y \\in [1, 2)\n/// $$\n///\n/// For $0 \\leq x \\lt 1$, the input is inverted:\n///\n/// $$\n/// log_2{x} = -log_2{\\frac{1}{x}}\n/// $$\n///\n/// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\n///\n/// Notes:\n/// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal.\n///\n/// Requirements:\n/// - x must be greater than zero.\n///\n/// @param x The UD60x18 number for which to calculate the binary logarithm.\n/// @return result The binary logarithm as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log2(UD60x18 x) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n\n    if (xUint < uUNIT) {\n        revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x);\n    }\n\n    unchecked {\n        // Calculate the integer part of the logarithm.\n        uint256 n = Common.msb(xUint / uUNIT);\n\n        // This is the integer part of the logarithm as a UD60x18 number. The operation can't overflow because n\n        // n is at most 255 and UNIT is 1e18.\n        uint256 resultUint = n * uUNIT;\n\n        // Calculate $y = x * 2^{-n}$.\n        uint256 y = xUint >> n;\n\n        // If y is the unit number, the fractional part is zero.\n        if (y == uUNIT) {\n            return wrap(resultUint);\n        }\n\n        // Calculate the fractional part via the iterative approximation.\n        // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient.\n        uint256 DOUBLE_UNIT = 2e18;\n        for (uint256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {\n            y = (y * y) / uUNIT;\n\n            // Is y^2 >= 2e18 and so in the range [2e18, 4e18)?\n            if (y >= DOUBLE_UNIT) {\n                // Add the 2^{-m} factor to the logarithm.\n                resultUint += delta;\n\n                // Halve y, which corresponds to z/2 in the Wikipedia article.\n                y >>= 1;\n            }\n        }\n        result = wrap(resultUint);\n    }\n}\n\n/// @notice Multiplies two UD60x18 numbers together, returning a new UD60x18 number.\n///\n/// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv}.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv}.\n///\n/// @dev See the documentation in {Common.mulDiv18}.\n/// @param x The multiplicand as a UD60x18 number.\n/// @param y The multiplier as a UD60x18 number.\n/// @return result The product as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction mul(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    result = wrap(Common.mulDiv18(x.unwrap(), y.unwrap()));\n}\n\n/// @notice Raises x to the power of y.\n///\n/// For $1 \\leq x \\leq \\infty$, the following standard formula is used:\n///\n/// $$\n/// x^y = 2^{log_2{x} * y}\n/// $$\n///\n/// For $0 \\leq x \\lt 1$, since the unsigned {log2} is undefined, an equivalent formula is used:\n///\n/// $$\n/// i = \\frac{1}{x}\n/// w = 2^{log_2{i} * y}\n/// x^y = \\frac{1}{w}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2} and {mul}.\n/// - Returns `UNIT` for 0^0.\n/// - It may not perform well with very small values of x. Consider using SD59x18 as an alternative.\n///\n/// Requirements:\n/// - Refer to the requirements in {exp2}, {log2}, and {mul}.\n///\n/// @param x The base as a UD60x18 number.\n/// @param y The exponent as a UD60x18 number.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction pow(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n    uint256 yUint = y.unwrap();\n\n    // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero.\n    if (xUint == 0) {\n        return yUint == 0 ? UNIT : ZERO;\n    }\n    // If x is `UNIT`, the result is always `UNIT`.\n    else if (xUint == uUNIT) {\n        return UNIT;\n    }\n\n    // If y is zero, the result is always `UNIT`.\n    if (yUint == 0) {\n        return UNIT;\n    }\n    // If y is `UNIT`, the result is always x.\n    else if (yUint == uUNIT) {\n        return x;\n    }\n\n    // If x is greater than `UNIT`, use the standard formula.\n    if (xUint > uUNIT) {\n        result = exp2(mul(log2(x), y));\n    }\n    // Conversely, if x is less than `UNIT`, use the equivalent formula.\n    else {\n        UD60x18 i = wrap(uUNIT_SQUARED / xUint);\n        UD60x18 w = exp2(mul(log2(i), y));\n        result = wrap(uUNIT_SQUARED / w.unwrap());\n    }\n}\n\n/// @notice Raises x (a UD60x18 number) to the power y (an unsigned basic integer) using the well-known\n/// algorithm \"exponentiation by squaring\".\n///\n/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv18}.\n/// - Returns `UNIT` for 0^0.\n///\n/// Requirements:\n/// - The result must fit in UD60x18.\n///\n/// @param x The base as a UD60x18 number.\n/// @param y The exponent as a uint256.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction powu(UD60x18 x, uint256 y) pure returns (UD60x18 result) {\n    // Calculate the first iteration of the loop in advance.\n    uint256 xUint = x.unwrap();\n    uint256 resultUint = y & 1 > 0 ? xUint : uUNIT;\n\n    // Equivalent to `for(y /= 2; y > 0; y /= 2)`.\n    for (y >>= 1; y > 0; y >>= 1) {\n        xUint = Common.mulDiv18(xUint, xUint);\n\n        // Equivalent to `y % 2 == 1`.\n        if (y & 1 > 0) {\n            resultUint = Common.mulDiv18(resultUint, xUint);\n        }\n    }\n    result = wrap(resultUint);\n}\n\n/// @notice Calculates the square root of x using the Babylonian method.\n///\n/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n///\n/// Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x must be less than `MAX_UD60x18 / UNIT`.\n///\n/// @param x The UD60x18 number for which to calculate the square root.\n/// @return result The result as a UD60x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction sqrt(UD60x18 x) pure returns (UD60x18 result) {\n    uint256 xUint = x.unwrap();\n\n    unchecked {\n        if (xUint > uMAX_UD60x18 / uUNIT) {\n            revert Errors.PRBMath_UD60x18_Sqrt_Overflow(x);\n        }\n        // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two UD60x18 numbers.\n        // In this case, the two numbers are both the square root.\n        result = wrap(Common.sqrt(xUint * uUNIT));\n    }\n}\n"
      },
      "lib/prb-math/src/ud60x18/ValueType.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\nimport \"./Helpers.sol\" as Helpers;\nimport \"./Math.sol\" as Math;\n\n/// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256.\n/// @dev The value type is defined here so it can be imported in all other files.\ntype UD60x18 is uint256;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n    Casting.intoSD1x18,\n    Casting.intoUD2x18,\n    Casting.intoSD59x18,\n    Casting.intoUint128,\n    Casting.intoUint256,\n    Casting.intoUint40,\n    Casting.unwrap\n} for UD60x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n                            MATHEMATICAL FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes the functions in this library callable on the UD60x18 type.\nusing {\n    Math.avg,\n    Math.ceil,\n    Math.div,\n    Math.exp,\n    Math.exp2,\n    Math.floor,\n    Math.frac,\n    Math.gm,\n    Math.inv,\n    Math.ln,\n    Math.log10,\n    Math.log2,\n    Math.mul,\n    Math.pow,\n    Math.powu,\n    Math.sqrt\n} for UD60x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                HELPER FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes the functions in this library callable on the UD60x18 type.\nusing {\n    Helpers.add,\n    Helpers.and,\n    Helpers.eq,\n    Helpers.gt,\n    Helpers.gte,\n    Helpers.isZero,\n    Helpers.lshift,\n    Helpers.lt,\n    Helpers.lte,\n    Helpers.mod,\n    Helpers.neq,\n    Helpers.not,\n    Helpers.or,\n    Helpers.rshift,\n    Helpers.sub,\n    Helpers.uncheckedAdd,\n    Helpers.uncheckedSub,\n    Helpers.xor\n} for UD60x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    OPERATORS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes it possible to use these operators on the UD60x18 type.\nusing {\n    Helpers.add as +,\n    Helpers.and2 as &,\n    Math.div as /,\n    Helpers.eq as ==,\n    Helpers.gt as >,\n    Helpers.gte as >=,\n    Helpers.lt as <,\n    Helpers.lte as <=,\n    Helpers.or as |,\n    Helpers.mod as %,\n    Math.mul as *,\n    Helpers.neq as !=,\n    Helpers.not as ~,\n    Helpers.sub as -,\n    Helpers.xor as ^\n} for UD60x18 global;\n"
      },
      "lib/rain.math.fixedpoint/src/lib/FixedPointDecimalConstants.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev The scale of all fixed point math. This is adopting the conventions of\n/// both ETH (wei) and most ERC20 tokens, so is hopefully uncontroversial.\nuint256 constant FIXED_POINT_DECIMALS = 18;\n\n/// @dev Value of \"one\" for fixed point math.\nuint256 constant FIXED_POINT_ONE = 1e18;\n\n/// @dev Calculations MUST round up.\nuint256 constant FLAG_ROUND_UP = 1;\n\n/// @dev Calculations MUST saturate NOT overflow.\nuint256 constant FLAG_SATURATE = 1 << 1;\n\n/// @dev Flags MUST NOT exceed this value.\nuint256 constant FLAG_MAX_INT = FLAG_SATURATE | FLAG_ROUND_UP;\n\n/// @dev Can't represent this many OOMs of decimals in `uint256`.\nuint256 constant OVERFLOW_RESCALE_OOMS = 78;\n"
      },
      "lib/rain.interpreter.interface/src/interface/deprecated/IInterpreterExternV1.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\ntype EncodedExternDispatch is uint256;\n\ntype ExternDispatch is uint256;\n\n/// @title IInterpreterExternV1\n/// Handle a single dispatch from some calling contract with an array of\n/// inputs and array of outputs. Ostensibly useful to build \"word packs\" for\n/// `IInterpreterV1` so that less frequently used words can be provided in\n/// a less efficient format, but without bloating the base interpreter in\n/// terms of code size. Effectively allows unlimited words to exist as externs\n/// alongside interpreters.\ninterface IInterpreterExternV1 {\n    /// Handles a single dispatch.\n    /// @param dispatch Encoded information about the extern to dispatch.\n    /// Analogous to the opcode/operand in the interpreter.\n    /// @param inputs The array of inputs for the dispatched logic.\n    /// @return outputs The result of the dispatched logic.\n    function extern(ExternDispatch dispatch, uint256[] memory inputs)\n        external\n        view\n        returns (uint256[] memory outputs);\n}\n"
      },
      "lib/prb-math/src/Common.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\n// Common.sol\n//\n// Common mathematical functions needed by both SD59x18 and UD60x18. Note that these global functions do not\n// always operate with SD59x18 and UD60x18 numbers.\n\n/*//////////////////////////////////////////////////////////////////////////\n                                CUSTOM ERRORS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Thrown when the resultant value in {mulDiv} overflows uint256.\nerror PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator);\n\n/// @notice Thrown when the resultant value in {mulDiv18} overflows uint256.\nerror PRBMath_MulDiv18_Overflow(uint256 x, uint256 y);\n\n/// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`.\nerror PRBMath_MulDivSigned_InputTooSmall();\n\n/// @notice Thrown when the resultant value in {mulDivSigned} overflows int256.\nerror PRBMath_MulDivSigned_Overflow(int256 x, int256 y);\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    CONSTANTS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @dev The maximum value a uint128 number can have.\nuint128 constant MAX_UINT128 = type(uint128).max;\n\n/// @dev The maximum value a uint40 number can have.\nuint40 constant MAX_UINT40 = type(uint40).max;\n\n/// @dev The unit number, which the decimal precision of the fixed-point types.\nuint256 constant UNIT = 1e18;\n\n/// @dev The unit number inverted mod 2^256.\nuint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\n\n/// @dev The the largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant\n/// bit in the binary representation of `UNIT`.\nuint256 constant UNIT_LPOTD = 262144;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\n/// @notice Calculates the binary exponent of x using the binary fraction method.\n/// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693.\n/// @param x The exponent as an unsigned 192.64-bit fixed-point number.\n/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp2(uint256 x) pure returns (uint256 result) {\n    unchecked {\n        // Start from 0.5 in the 192.64-bit fixed-point format.\n        result = 0x800000000000000000000000000000000000000000000000;\n\n        // The following logic multiplies the result by $\\sqrt{2^{-i}}$ when the bit at position i is 1. Key points:\n        //\n        // 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65.\n        // 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing\n        // a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1,\n        // we know that `x & 0xFF` is also 1.\n        if (x & 0xFF00000000000000 > 0) {\n            if (x & 0x8000000000000000 > 0) {\n                result = (result * 0x16A09E667F3BCC909) >> 64;\n            }\n            if (x & 0x4000000000000000 > 0) {\n                result = (result * 0x1306FE0A31B7152DF) >> 64;\n            }\n            if (x & 0x2000000000000000 > 0) {\n                result = (result * 0x1172B83C7D517ADCE) >> 64;\n            }\n            if (x & 0x1000000000000000 > 0) {\n                result = (result * 0x10B5586CF9890F62A) >> 64;\n            }\n            if (x & 0x800000000000000 > 0) {\n                result = (result * 0x1059B0D31585743AE) >> 64;\n            }\n            if (x & 0x400000000000000 > 0) {\n                result = (result * 0x102C9A3E778060EE7) >> 64;\n            }\n            if (x & 0x200000000000000 > 0) {\n                result = (result * 0x10163DA9FB33356D8) >> 64;\n            }\n            if (x & 0x100000000000000 > 0) {\n                result = (result * 0x100B1AFA5ABCBED61) >> 64;\n            }\n        }\n\n        if (x & 0xFF000000000000 > 0) {\n            if (x & 0x80000000000000 > 0) {\n                result = (result * 0x10058C86DA1C09EA2) >> 64;\n            }\n            if (x & 0x40000000000000 > 0) {\n                result = (result * 0x1002C605E2E8CEC50) >> 64;\n            }\n            if (x & 0x20000000000000 > 0) {\n                result = (result * 0x100162F3904051FA1) >> 64;\n            }\n            if (x & 0x10000000000000 > 0) {\n                result = (result * 0x1000B175EFFDC76BA) >> 64;\n            }\n            if (x & 0x8000000000000 > 0) {\n                result = (result * 0x100058BA01FB9F96D) >> 64;\n            }\n            if (x & 0x4000000000000 > 0) {\n                result = (result * 0x10002C5CC37DA9492) >> 64;\n            }\n            if (x & 0x2000000000000 > 0) {\n                result = (result * 0x1000162E525EE0547) >> 64;\n            }\n            if (x & 0x1000000000000 > 0) {\n                result = (result * 0x10000B17255775C04) >> 64;\n            }\n        }\n\n        if (x & 0xFF0000000000 > 0) {\n            if (x & 0x800000000000 > 0) {\n                result = (result * 0x1000058B91B5BC9AE) >> 64;\n            }\n            if (x & 0x400000000000 > 0) {\n                result = (result * 0x100002C5C89D5EC6D) >> 64;\n            }\n            if (x & 0x200000000000 > 0) {\n                result = (result * 0x10000162E43F4F831) >> 64;\n            }\n            if (x & 0x100000000000 > 0) {\n                result = (result * 0x100000B1721BCFC9A) >> 64;\n            }\n            if (x & 0x80000000000 > 0) {\n                result = (result * 0x10000058B90CF1E6E) >> 64;\n            }\n            if (x & 0x40000000000 > 0) {\n                result = (result * 0x1000002C5C863B73F) >> 64;\n            }\n            if (x & 0x20000000000 > 0) {\n                result = (result * 0x100000162E430E5A2) >> 64;\n            }\n            if (x & 0x10000000000 > 0) {\n                result = (result * 0x1000000B172183551) >> 64;\n            }\n        }\n\n        if (x & 0xFF00000000 > 0) {\n            if (x & 0x8000000000 > 0) {\n                result = (result * 0x100000058B90C0B49) >> 64;\n            }\n            if (x & 0x4000000000 > 0) {\n                result = (result * 0x10000002C5C8601CC) >> 64;\n            }\n            if (x & 0x2000000000 > 0) {\n                result = (result * 0x1000000162E42FFF0) >> 64;\n            }\n            if (x & 0x1000000000 > 0) {\n                result = (result * 0x10000000B17217FBB) >> 64;\n            }\n            if (x & 0x800000000 > 0) {\n                result = (result * 0x1000000058B90BFCE) >> 64;\n            }\n            if (x & 0x400000000 > 0) {\n                result = (result * 0x100000002C5C85FE3) >> 64;\n            }\n            if (x & 0x200000000 > 0) {\n                result = (result * 0x10000000162E42FF1) >> 64;\n            }\n            if (x & 0x100000000 > 0) {\n                result = (result * 0x100000000B17217F8) >> 64;\n            }\n        }\n\n        if (x & 0xFF000000 > 0) {\n            if (x & 0x80000000 > 0) {\n                result = (result * 0x10000000058B90BFC) >> 64;\n            }\n            if (x & 0x40000000 > 0) {\n                result = (result * 0x1000000002C5C85FE) >> 64;\n            }\n            if (x & 0x20000000 > 0) {\n                result = (result * 0x100000000162E42FF) >> 64;\n            }\n            if (x & 0x10000000 > 0) {\n                result = (result * 0x1000000000B17217F) >> 64;\n            }\n            if (x & 0x8000000 > 0) {\n                result = (result * 0x100000000058B90C0) >> 64;\n            }\n            if (x & 0x4000000 > 0) {\n                result = (result * 0x10000000002C5C860) >> 64;\n            }\n            if (x & 0x2000000 > 0) {\n                result = (result * 0x1000000000162E430) >> 64;\n            }\n            if (x & 0x1000000 > 0) {\n                result = (result * 0x10000000000B17218) >> 64;\n            }\n        }\n\n        if (x & 0xFF0000 > 0) {\n            if (x & 0x800000 > 0) {\n                result = (result * 0x1000000000058B90C) >> 64;\n            }\n            if (x & 0x400000 > 0) {\n                result = (result * 0x100000000002C5C86) >> 64;\n            }\n            if (x & 0x200000 > 0) {\n                result = (result * 0x10000000000162E43) >> 64;\n            }\n            if (x & 0x100000 > 0) {\n                result = (result * 0x100000000000B1721) >> 64;\n            }\n            if (x & 0x80000 > 0) {\n                result = (result * 0x10000000000058B91) >> 64;\n            }\n            if (x & 0x40000 > 0) {\n                result = (result * 0x1000000000002C5C8) >> 64;\n            }\n            if (x & 0x20000 > 0) {\n                result = (result * 0x100000000000162E4) >> 64;\n            }\n            if (x & 0x10000 > 0) {\n                result = (result * 0x1000000000000B172) >> 64;\n            }\n        }\n\n        if (x & 0xFF00 > 0) {\n            if (x & 0x8000 > 0) {\n                result = (result * 0x100000000000058B9) >> 64;\n            }\n            if (x & 0x4000 > 0) {\n                result = (result * 0x10000000000002C5D) >> 64;\n            }\n            if (x & 0x2000 > 0) {\n                result = (result * 0x1000000000000162E) >> 64;\n            }\n            if (x & 0x1000 > 0) {\n                result = (result * 0x10000000000000B17) >> 64;\n            }\n            if (x & 0x800 > 0) {\n                result = (result * 0x1000000000000058C) >> 64;\n            }\n            if (x & 0x400 > 0) {\n                result = (result * 0x100000000000002C6) >> 64;\n            }\n            if (x & 0x200 > 0) {\n                result = (result * 0x10000000000000163) >> 64;\n            }\n            if (x & 0x100 > 0) {\n                result = (result * 0x100000000000000B1) >> 64;\n            }\n        }\n\n        if (x & 0xFF > 0) {\n            if (x & 0x80 > 0) {\n                result = (result * 0x10000000000000059) >> 64;\n            }\n            if (x & 0x40 > 0) {\n                result = (result * 0x1000000000000002C) >> 64;\n            }\n            if (x & 0x20 > 0) {\n                result = (result * 0x10000000000000016) >> 64;\n            }\n            if (x & 0x10 > 0) {\n                result = (result * 0x1000000000000000B) >> 64;\n            }\n            if (x & 0x8 > 0) {\n                result = (result * 0x10000000000000006) >> 64;\n            }\n            if (x & 0x4 > 0) {\n                result = (result * 0x10000000000000003) >> 64;\n            }\n            if (x & 0x2 > 0) {\n                result = (result * 0x10000000000000001) >> 64;\n            }\n            if (x & 0x1 > 0) {\n                result = (result * 0x10000000000000001) >> 64;\n            }\n        }\n\n        // In the code snippet below, two operations are executed simultaneously:\n        //\n        // 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1\n        // accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192.\n        // 2. The result is then converted to an unsigned 60.18-decimal fixed-point format.\n        //\n        // The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the,\n        // integer part, $2^n$.\n        result *= UNIT;\n        result >>= (191 - (x >> 64));\n    }\n}\n\n/// @notice Finds the zero-based index of the first 1 in the binary representation of x.\n///\n/// @dev See the note on \"msb\" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set\n///\n/// Each step in this implementation is equivalent to this high-level code:\n///\n/// ```solidity\n/// if (x >= 2 ** 128) {\n///     x >>= 128;\n///     result += 128;\n/// }\n/// ```\n///\n/// Where 128 is replaced with each respective power of two factor. See the full high-level implementation here:\n/// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948\n///\n/// The Yul instructions used below are:\n///\n/// - \"gt\" is \"greater than\"\n/// - \"or\" is the OR bitwise operator\n/// - \"shl\" is \"shift left\"\n/// - \"shr\" is \"shift right\"\n///\n/// @param x The uint256 number for which to find the index of the most significant bit.\n/// @return result The index of the most significant bit as a uint256.\n/// @custom:smtchecker abstract-function-nondet\nfunction msb(uint256 x) pure returns (uint256 result) {\n    // 2^128\n    assembly (\"memory-safe\") {\n        let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n        x := shr(factor, x)\n        result := or(result, factor)\n    }\n    // 2^64\n    assembly (\"memory-safe\") {\n        let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n        x := shr(factor, x)\n        result := or(result, factor)\n    }\n    // 2^32\n    assembly (\"memory-safe\") {\n        let factor := shl(5, gt(x, 0xFFFFFFFF))\n        x := shr(factor, x)\n        result := or(result, factor)\n    }\n    // 2^16\n    assembly (\"memory-safe\") {\n        let factor := shl(4, gt(x, 0xFFFF))\n        x := shr(factor, x)\n        result := or(result, factor)\n    }\n    // 2^8\n    assembly (\"memory-safe\") {\n        let factor := shl(3, gt(x, 0xFF))\n        x := shr(factor, x)\n        result := or(result, factor)\n    }\n    // 2^4\n    assembly (\"memory-safe\") {\n        let factor := shl(2, gt(x, 0xF))\n        x := shr(factor, x)\n        result := or(result, factor)\n    }\n    // 2^2\n    assembly (\"memory-safe\") {\n        let factor := shl(1, gt(x, 0x3))\n        x := shr(factor, x)\n        result := or(result, factor)\n    }\n    // 2^1\n    // No need to shift x any more.\n    assembly (\"memory-safe\") {\n        let factor := gt(x, 0x1)\n        result := or(result, factor)\n    }\n}\n\n/// @notice Calculates x*y÷denominator with 512-bit precision.\n///\n/// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\n///\n/// Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - The denominator must not be zero.\n/// - The result must fit in uint256.\n///\n/// @param x The multiplicand as a uint256.\n/// @param y The multiplier as a uint256.\n/// @param denominator The divisor as a uint256.\n/// @return result The result as a uint256.\n/// @custom:smtchecker abstract-function-nondet\nfunction mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) {\n    // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n    // use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256\n    // variables such that product = prod1 * 2^256 + prod0.\n    uint256 prod0; // Least significant 256 bits of the product\n    uint256 prod1; // Most significant 256 bits of the product\n    assembly (\"memory-safe\") {\n        let mm := mulmod(x, y, not(0))\n        prod0 := mul(x, y)\n        prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n    }\n\n    // Handle non-overflow cases, 256 by 256 division.\n    if (prod1 == 0) {\n        unchecked {\n            return prod0 / denominator;\n        }\n    }\n\n    // Make sure the result is less than 2^256. Also prevents denominator == 0.\n    if (prod1 >= denominator) {\n        revert PRBMath_MulDiv_Overflow(x, y, denominator);\n    }\n\n    ////////////////////////////////////////////////////////////////////////////\n    // 512 by 256 division\n    ////////////////////////////////////////////////////////////////////////////\n\n    // Make division exact by subtracting the remainder from [prod1 prod0].\n    uint256 remainder;\n    assembly (\"memory-safe\") {\n        // Compute remainder using the mulmod Yul instruction.\n        remainder := mulmod(x, y, denominator)\n\n        // Subtract 256 bit number from 512-bit number.\n        prod1 := sub(prod1, gt(remainder, prod0))\n        prod0 := sub(prod0, remainder)\n    }\n\n    unchecked {\n        // Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow\n        // because the denominator cannot be zero at this point in the function execution. The result is always >= 1.\n        // For more detail, see https://cs.stackexchange.com/q/138556/92363.\n        uint256 lpotdod = denominator & (~denominator + 1);\n        uint256 flippedLpotdod;\n\n        assembly (\"memory-safe\") {\n            // Factor powers of two out of denominator.\n            denominator := div(denominator, lpotdod)\n\n            // Divide [prod1 prod0] by lpotdod.\n            prod0 := div(prod0, lpotdod)\n\n            // Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one.\n            // `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits.\n            // However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693\n            flippedLpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\n        }\n\n        // Shift in bits from prod1 into prod0.\n        prod0 |= prod1 * flippedLpotdod;\n\n        // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n        // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n        // four bits. That is, denominator * inv = 1 mod 2^4.\n        uint256 inverse = (3 * denominator) ^ 2;\n\n        // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n        // in modular arithmetic, doubling the correct bits in each step.\n        inverse *= 2 - denominator * inverse; // inverse mod 2^8\n        inverse *= 2 - denominator * inverse; // inverse mod 2^16\n        inverse *= 2 - denominator * inverse; // inverse mod 2^32\n        inverse *= 2 - denominator * inverse; // inverse mod 2^64\n        inverse *= 2 - denominator * inverse; // inverse mod 2^128\n        inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n        // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n        // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n        // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n        // is no longer required.\n        result = prod0 * inverse;\n    }\n}\n\n/// @notice Calculates x*y÷1e18 with 512-bit precision.\n///\n/// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18.\n///\n/// Notes:\n/// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}.\n/// - The result is rounded toward zero.\n/// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations:\n///\n/// $$\n/// \\begin{cases}\n///     x * y = MAX\\_UINT256 * UNIT \\\\\n///     (x * y) \\% UNIT \\geq \\frac{UNIT}{2}\n/// \\end{cases}\n/// $$\n///\n/// Requirements:\n/// - Refer to the requirements in {mulDiv}.\n/// - The result must fit in uint256.\n///\n/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n/// @custom:smtchecker abstract-function-nondet\nfunction mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) {\n    uint256 prod0;\n    uint256 prod1;\n    assembly (\"memory-safe\") {\n        let mm := mulmod(x, y, not(0))\n        prod0 := mul(x, y)\n        prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n    }\n\n    if (prod1 == 0) {\n        unchecked {\n            return prod0 / UNIT;\n        }\n    }\n\n    if (prod1 >= UNIT) {\n        revert PRBMath_MulDiv18_Overflow(x, y);\n    }\n\n    uint256 remainder;\n    assembly (\"memory-safe\") {\n        remainder := mulmod(x, y, UNIT)\n        result :=\n            mul(\n                or(\n                    div(sub(prod0, remainder), UNIT_LPOTD),\n                    mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1))\n                ),\n                UNIT_INVERSE\n            )\n    }\n}\n\n/// @notice Calculates x*y÷denominator with 512-bit precision.\n///\n/// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately.\n///\n/// Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - Refer to the requirements in {mulDiv}.\n/// - None of the inputs can be `type(int256).min`.\n/// - The result must fit in int256.\n///\n/// @param x The multiplicand as an int256.\n/// @param y The multiplier as an int256.\n/// @param denominator The divisor as an int256.\n/// @return result The result as an int256.\n/// @custom:smtchecker abstract-function-nondet\nfunction mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) {\n    if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\n        revert PRBMath_MulDivSigned_InputTooSmall();\n    }\n\n    // Get hold of the absolute values of x, y and the denominator.\n    uint256 xAbs;\n    uint256 yAbs;\n    uint256 dAbs;\n    unchecked {\n        xAbs = x < 0 ? uint256(-x) : uint256(x);\n        yAbs = y < 0 ? uint256(-y) : uint256(y);\n        dAbs = denominator < 0 ? uint256(-denominator) : uint256(denominator);\n    }\n\n    // Compute the absolute value of x*y÷denominator. The result must fit in int256.\n    uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs);\n    if (resultAbs > uint256(type(int256).max)) {\n        revert PRBMath_MulDivSigned_Overflow(x, y);\n    }\n\n    // Get the signs of x, y and the denominator.\n    uint256 sx;\n    uint256 sy;\n    uint256 sd;\n    assembly (\"memory-safe\") {\n        // \"sgt\" is the \"signed greater than\" assembly instruction and \"sub(0,1)\" is -1 in two's complement.\n        sx := sgt(x, sub(0, 1))\n        sy := sgt(y, sub(0, 1))\n        sd := sgt(denominator, sub(0, 1))\n    }\n\n    // XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs.\n    // If there are, the result should be negative. Otherwise, it should be positive.\n    unchecked {\n        result = sx ^ sy ^ sd == 0 ? -int256(resultAbs) : int256(resultAbs);\n    }\n}\n\n/// @notice Calculates the square root of x using the Babylonian method.\n///\n/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n///\n/// Notes:\n/// - If x is not a perfect square, the result is rounded down.\n/// - Credits to OpenZeppelin for the explanations in comments below.\n///\n/// @param x The uint256 number for which to calculate the square root.\n/// @return result The result as a uint256.\n/// @custom:smtchecker abstract-function-nondet\nfunction sqrt(uint256 x) pure returns (uint256 result) {\n    if (x == 0) {\n        return 0;\n    }\n\n    // For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x.\n    //\n    // We know that the \"msb\" (most significant bit) of x is a power of 2 such that we have:\n    //\n    // $$\n    // msb(x) <= x <= 2*msb(x)$\n    // $$\n    //\n    // We write $msb(x)$ as $2^k$, and we get:\n    //\n    // $$\n    // k = log_2(x)\n    // $$\n    //\n    // Thus, we can write the initial inequality as:\n    //\n    // $$\n    // 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\\\\n    // sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\\\\n    // 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1}\n    // $$\n    //\n    // Consequently, $2^{log_2(x) /2} is a good first approximation of sqrt(x) with at least one correct bit.\n    uint256 xAux = uint256(x);\n    result = 1;\n    if (xAux >= 2 ** 128) {\n        xAux >>= 128;\n        result <<= 64;\n    }\n    if (xAux >= 2 ** 64) {\n        xAux >>= 64;\n        result <<= 32;\n    }\n    if (xAux >= 2 ** 32) {\n        xAux >>= 32;\n        result <<= 16;\n    }\n    if (xAux >= 2 ** 16) {\n        xAux >>= 16;\n        result <<= 8;\n    }\n    if (xAux >= 2 ** 8) {\n        xAux >>= 8;\n        result <<= 4;\n    }\n    if (xAux >= 2 ** 4) {\n        xAux >>= 4;\n        result <<= 2;\n    }\n    if (xAux >= 2 ** 2) {\n        result <<= 1;\n    }\n\n    // At this point, `result` is an estimation with at least one bit of precision. We know the true value has at\n    // most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision\n    // doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of\n    // precision into the expected uint128 result.\n    unchecked {\n        result = (result + x / result) >> 1;\n        result = (result + x / result) >> 1;\n        result = (result + x / result) >> 1;\n        result = (result + x / result) >> 1;\n        result = (result + x / result) >> 1;\n        result = (result + x / result) >> 1;\n        result = (result + x / result) >> 1;\n\n        // If x is not a perfect square, round the result toward zero.\n        uint256 roundedResult = x / result;\n        if (result >= roundedResult) {\n            result = roundedResult;\n        }\n    }\n}\n"
      },
      "lib/prb-math/src/sd1x18/Constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD1x18 } from \"./ValueType.sol\";\n\n/// @dev Euler's number as an SD1x18 number.\nSD1x18 constant E = SD1x18.wrap(2_718281828459045235);\n\n/// @dev The maximum value an SD1x18 number can have.\nint64 constant uMAX_SD1x18 = 9_223372036854775807;\nSD1x18 constant MAX_SD1x18 = SD1x18.wrap(uMAX_SD1x18);\n\n/// @dev The maximum value an SD1x18 number can have.\nint64 constant uMIN_SD1x18 = -9_223372036854775808;\nSD1x18 constant MIN_SD1x18 = SD1x18.wrap(uMIN_SD1x18);\n\n/// @dev PI as an SD1x18 number.\nSD1x18 constant PI = SD1x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of SD1x18.\nSD1x18 constant UNIT = SD1x18.wrap(1e18);\nint256 constant uUNIT = 1e18;\n"
      },
      "lib/prb-math/src/sd1x18/ValueType.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\n\n/// @notice The signed 1.18-decimal fixed-point number representation, which can have up to 1 digit and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type int64. This is useful when end users want to use int64 to save gas, e.g. with tight variable packing in contract\n/// storage.\ntype SD1x18 is int64;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n    Casting.intoSD59x18,\n    Casting.intoUD2x18,\n    Casting.intoUD60x18,\n    Casting.intoUint256,\n    Casting.intoUint128,\n    Casting.intoUint40,\n    Casting.unwrap\n} for SD1x18 global;\n"
      },
      "lib/prb-math/src/sd59x18/Constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD59x18 } from \"./ValueType.sol\";\n\n// NOTICE: the \"u\" prefix stands for \"unwrapped\".\n\n/// @dev Euler's number as an SD59x18 number.\nSD59x18 constant E = SD59x18.wrap(2_718281828459045235);\n\n/// @dev The maximum input permitted in {exp}.\nint256 constant uEXP_MAX_INPUT = 133_084258667509499440;\nSD59x18 constant EXP_MAX_INPUT = SD59x18.wrap(uEXP_MAX_INPUT);\n\n/// @dev The maximum input permitted in {exp2}.\nint256 constant uEXP2_MAX_INPUT = 192e18 - 1;\nSD59x18 constant EXP2_MAX_INPUT = SD59x18.wrap(uEXP2_MAX_INPUT);\n\n/// @dev Half the UNIT number.\nint256 constant uHALF_UNIT = 0.5e18;\nSD59x18 constant HALF_UNIT = SD59x18.wrap(uHALF_UNIT);\n\n/// @dev $log_2(10)$ as an SD59x18 number.\nint256 constant uLOG2_10 = 3_321928094887362347;\nSD59x18 constant LOG2_10 = SD59x18.wrap(uLOG2_10);\n\n/// @dev $log_2(e)$ as an SD59x18 number.\nint256 constant uLOG2_E = 1_442695040888963407;\nSD59x18 constant LOG2_E = SD59x18.wrap(uLOG2_E);\n\n/// @dev The maximum value an SD59x18 number can have.\nint256 constant uMAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967;\nSD59x18 constant MAX_SD59x18 = SD59x18.wrap(uMAX_SD59x18);\n\n/// @dev The maximum whole value an SD59x18 number can have.\nint256 constant uMAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000;\nSD59x18 constant MAX_WHOLE_SD59x18 = SD59x18.wrap(uMAX_WHOLE_SD59x18);\n\n/// @dev The minimum value an SD59x18 number can have.\nint256 constant uMIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968;\nSD59x18 constant MIN_SD59x18 = SD59x18.wrap(uMIN_SD59x18);\n\n/// @dev The minimum whole value an SD59x18 number can have.\nint256 constant uMIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000;\nSD59x18 constant MIN_WHOLE_SD59x18 = SD59x18.wrap(uMIN_WHOLE_SD59x18);\n\n/// @dev PI as an SD59x18 number.\nSD59x18 constant PI = SD59x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of SD59x18.\nint256 constant uUNIT = 1e18;\nSD59x18 constant UNIT = SD59x18.wrap(1e18);\n\n/// @dev The unit number squared.\nint256 constant uUNIT_SQUARED = 1e36;\nSD59x18 constant UNIT_SQUARED = SD59x18.wrap(uUNIT_SQUARED);\n\n/// @dev Zero as an SD59x18 number.\nSD59x18 constant ZERO = SD59x18.wrap(0);\n"
      },
      "lib/prb-math/src/sd59x18/ValueType.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\nimport \"./Helpers.sol\" as Helpers;\nimport \"./Math.sol\" as Math;\n\n/// @notice The signed 59.18-decimal fixed-point number representation, which can have up to 59 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type int256.\ntype SD59x18 is int256;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n    Casting.intoInt256,\n    Casting.intoSD1x18,\n    Casting.intoUD2x18,\n    Casting.intoUD60x18,\n    Casting.intoUint256,\n    Casting.intoUint128,\n    Casting.intoUint40,\n    Casting.unwrap\n} for SD59x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n                            MATHEMATICAL FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n    Math.abs,\n    Math.avg,\n    Math.ceil,\n    Math.div,\n    Math.exp,\n    Math.exp2,\n    Math.floor,\n    Math.frac,\n    Math.gm,\n    Math.inv,\n    Math.log10,\n    Math.log2,\n    Math.ln,\n    Math.mul,\n    Math.pow,\n    Math.powu,\n    Math.sqrt\n} for SD59x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                HELPER FUNCTIONS\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n    Helpers.add,\n    Helpers.and,\n    Helpers.eq,\n    Helpers.gt,\n    Helpers.gte,\n    Helpers.isZero,\n    Helpers.lshift,\n    Helpers.lt,\n    Helpers.lte,\n    Helpers.mod,\n    Helpers.neq,\n    Helpers.not,\n    Helpers.or,\n    Helpers.rshift,\n    Helpers.sub,\n    Helpers.uncheckedAdd,\n    Helpers.uncheckedSub,\n    Helpers.uncheckedUnary,\n    Helpers.xor\n} for SD59x18 global;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    OPERATORS\n//////////////////////////////////////////////////////////////////////////*/\n\n// The global \"using for\" directive makes it possible to use these operators on the SD59x18 type.\nusing {\n    Helpers.add as +,\n    Helpers.and2 as &,\n    Math.div as /,\n    Helpers.eq as ==,\n    Helpers.gt as >,\n    Helpers.gte as >=,\n    Helpers.lt as <,\n    Helpers.lte as <=,\n    Helpers.mod as %,\n    Math.mul as *,\n    Helpers.neq as !=,\n    Helpers.not as ~,\n    Helpers.or as |,\n    Helpers.sub as -,\n    Helpers.unary as -,\n    Helpers.xor as ^\n} for SD59x18 global;\n"
      },
      "lib/prb-math/src/ud2x18/Constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD2x18 } from \"./ValueType.sol\";\n\n/// @dev Euler's number as a UD2x18 number.\nUD2x18 constant E = UD2x18.wrap(2_718281828459045235);\n\n/// @dev The maximum value a UD2x18 number can have.\nuint64 constant uMAX_UD2x18 = 18_446744073709551615;\nUD2x18 constant MAX_UD2x18 = UD2x18.wrap(uMAX_UD2x18);\n\n/// @dev PI as a UD2x18 number.\nUD2x18 constant PI = UD2x18.wrap(3_141592653589793238);\n\n/// @dev The unit number, which gives the decimal precision of UD2x18.\nuint256 constant uUNIT = 1e18;\nUD2x18 constant UNIT = UD2x18.wrap(1e18);\n"
      },
      "lib/prb-math/src/ud2x18/ValueType.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Casting.sol\" as Casting;\n\n/// @notice The unsigned 2.18-decimal fixed-point number representation, which can have up to 2 digits and up to 18\n/// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity\n/// type uint64. This is useful when end users want to use uint64 to save gas, e.g. with tight variable packing in contract\n/// storage.\ntype UD2x18 is uint64;\n\n/*//////////////////////////////////////////////////////////////////////////\n                                    CASTING\n//////////////////////////////////////////////////////////////////////////*/\n\nusing {\n    Casting.intoSD1x18,\n    Casting.intoSD59x18,\n    Casting.intoUD60x18,\n    Casting.intoUint256,\n    Casting.intoUint128,\n    Casting.intoUint40,\n    Casting.unwrap\n} for UD2x18 global;\n"
      },
      "lib/prb-math/src/sd1x18/Casting.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as CastingErrors;\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { UD2x18 } from \"../ud2x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { SD1x18 } from \"./ValueType.sol\";\n\n/// @notice Casts an SD1x18 number into SD59x18.\n/// @dev There is no overflow check because the domain of SD1x18 is a subset of SD59x18.\nfunction intoSD59x18(SD1x18 x) pure returns (SD59x18 result) {\n    result = SD59x18.wrap(int256(SD1x18.unwrap(x)));\n}\n\n/// @notice Casts an SD1x18 number into UD2x18.\n/// - x must be positive.\nfunction intoUD2x18(SD1x18 x) pure returns (UD2x18 result) {\n    int64 xInt = SD1x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD1x18_ToUD2x18_Underflow(x);\n    }\n    result = UD2x18.wrap(uint64(xInt));\n}\n\n/// @notice Casts an SD1x18 number into UD60x18.\n/// @dev Requirements:\n/// - x must be positive.\nfunction intoUD60x18(SD1x18 x) pure returns (UD60x18 result) {\n    int64 xInt = SD1x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD1x18_ToUD60x18_Underflow(x);\n    }\n    result = UD60x18.wrap(uint64(xInt));\n}\n\n/// @notice Casts an SD1x18 number into uint256.\n/// @dev Requirements:\n/// - x must be positive.\nfunction intoUint256(SD1x18 x) pure returns (uint256 result) {\n    int64 xInt = SD1x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD1x18_ToUint256_Underflow(x);\n    }\n    result = uint256(uint64(xInt));\n}\n\n/// @notice Casts an SD1x18 number into uint128.\n/// @dev Requirements:\n/// - x must be positive.\nfunction intoUint128(SD1x18 x) pure returns (uint128 result) {\n    int64 xInt = SD1x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD1x18_ToUint128_Underflow(x);\n    }\n    result = uint128(uint64(xInt));\n}\n\n/// @notice Casts an SD1x18 number into uint40.\n/// @dev Requirements:\n/// - x must be positive.\n/// - x must be less than or equal to `MAX_UINT40`.\nfunction intoUint40(SD1x18 x) pure returns (uint40 result) {\n    int64 xInt = SD1x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD1x18_ToUint40_Underflow(x);\n    }\n    if (xInt > int64(uint64(Common.MAX_UINT40))) {\n        revert CastingErrors.PRBMath_SD1x18_ToUint40_Overflow(x);\n    }\n    result = uint40(uint64(xInt));\n}\n\n/// @notice Alias for {wrap}.\nfunction sd1x18(int64 x) pure returns (SD1x18 result) {\n    result = SD1x18.wrap(x);\n}\n\n/// @notice Unwraps an SD1x18 number into int64.\nfunction unwrap(SD1x18 x) pure returns (int64 result) {\n    result = SD1x18.unwrap(x);\n}\n\n/// @notice Wraps an int64 number into SD1x18.\nfunction wrap(int64 x) pure returns (SD1x18 result) {\n    result = SD1x18.wrap(x);\n}\n"
      },
      "lib/prb-math/src/sd59x18/Casting.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"./Errors.sol\" as CastingErrors;\nimport { MAX_UINT128, MAX_UINT40 } from \"../Common.sol\";\nimport { uMAX_SD1x18, uMIN_SD1x18 } from \"../sd1x18/Constants.sol\";\nimport { SD1x18 } from \"../sd1x18/ValueType.sol\";\nimport { uMAX_UD2x18 } from \"../ud2x18/Constants.sol\";\nimport { UD2x18 } from \"../ud2x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Casts an SD59x18 number into int256.\n/// @dev This is basically a functional alias for {unwrap}.\nfunction intoInt256(SD59x18 x) pure returns (int256 result) {\n    result = SD59x18.unwrap(x);\n}\n\n/// @notice Casts an SD59x18 number into SD1x18.\n/// @dev Requirements:\n/// - x must be greater than or equal to `uMIN_SD1x18`.\n/// - x must be less than or equal to `uMAX_SD1x18`.\nfunction intoSD1x18(SD59x18 x) pure returns (SD1x18 result) {\n    int256 xInt = SD59x18.unwrap(x);\n    if (xInt < uMIN_SD1x18) {\n        revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Underflow(x);\n    }\n    if (xInt > uMAX_SD1x18) {\n        revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Overflow(x);\n    }\n    result = SD1x18.wrap(int64(xInt));\n}\n\n/// @notice Casts an SD59x18 number into UD2x18.\n/// @dev Requirements:\n/// - x must be positive.\n/// - x must be less than or equal to `uMAX_UD2x18`.\nfunction intoUD2x18(SD59x18 x) pure returns (UD2x18 result) {\n    int256 xInt = SD59x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Underflow(x);\n    }\n    if (xInt > int256(uint256(uMAX_UD2x18))) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Overflow(x);\n    }\n    result = UD2x18.wrap(uint64(uint256(xInt)));\n}\n\n/// @notice Casts an SD59x18 number into UD60x18.\n/// @dev Requirements:\n/// - x must be positive.\nfunction intoUD60x18(SD59x18 x) pure returns (UD60x18 result) {\n    int256 xInt = SD59x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUD60x18_Underflow(x);\n    }\n    result = UD60x18.wrap(uint256(xInt));\n}\n\n/// @notice Casts an SD59x18 number into uint256.\n/// @dev Requirements:\n/// - x must be positive.\nfunction intoUint256(SD59x18 x) pure returns (uint256 result) {\n    int256 xInt = SD59x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUint256_Underflow(x);\n    }\n    result = uint256(xInt);\n}\n\n/// @notice Casts an SD59x18 number into uint128.\n/// @dev Requirements:\n/// - x must be positive.\n/// - x must be less than or equal to `uMAX_UINT128`.\nfunction intoUint128(SD59x18 x) pure returns (uint128 result) {\n    int256 xInt = SD59x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUint128_Underflow(x);\n    }\n    if (xInt > int256(uint256(MAX_UINT128))) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUint128_Overflow(x);\n    }\n    result = uint128(uint256(xInt));\n}\n\n/// @notice Casts an SD59x18 number into uint40.\n/// @dev Requirements:\n/// - x must be positive.\n/// - x must be less than or equal to `MAX_UINT40`.\nfunction intoUint40(SD59x18 x) pure returns (uint40 result) {\n    int256 xInt = SD59x18.unwrap(x);\n    if (xInt < 0) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUint40_Underflow(x);\n    }\n    if (xInt > int256(uint256(MAX_UINT40))) {\n        revert CastingErrors.PRBMath_SD59x18_IntoUint40_Overflow(x);\n    }\n    result = uint40(uint256(xInt));\n}\n\n/// @notice Alias for {wrap}.\nfunction sd(int256 x) pure returns (SD59x18 result) {\n    result = SD59x18.wrap(x);\n}\n\n/// @notice Alias for {wrap}.\nfunction sd59x18(int256 x) pure returns (SD59x18 result) {\n    result = SD59x18.wrap(x);\n}\n\n/// @notice Unwraps an SD59x18 number into int256.\nfunction unwrap(SD59x18 x) pure returns (int256 result) {\n    result = SD59x18.unwrap(x);\n}\n\n/// @notice Wraps an int256 number into SD59x18.\nfunction wrap(int256 x) pure returns (SD59x18 result) {\n    result = SD59x18.wrap(x);\n}\n"
      },
      "lib/prb-math/src/sd59x18/Helpers.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { wrap } from \"./Casting.sol\";\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Implements the checked addition operation (+) in the SD59x18 type.\nfunction add(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    return wrap(x.unwrap() + y.unwrap());\n}\n\n/// @notice Implements the AND (&) bitwise operation in the SD59x18 type.\nfunction and(SD59x18 x, int256 bits) pure returns (SD59x18 result) {\n    return wrap(x.unwrap() & bits);\n}\n\n/// @notice Implements the AND (&) bitwise operation in the SD59x18 type.\nfunction and2(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    return wrap(x.unwrap() & y.unwrap());\n}\n\n/// @notice Implements the equal (=) operation in the SD59x18 type.\nfunction eq(SD59x18 x, SD59x18 y) pure returns (bool result) {\n    result = x.unwrap() == y.unwrap();\n}\n\n/// @notice Implements the greater than operation (>) in the SD59x18 type.\nfunction gt(SD59x18 x, SD59x18 y) pure returns (bool result) {\n    result = x.unwrap() > y.unwrap();\n}\n\n/// @notice Implements the greater than or equal to operation (>=) in the SD59x18 type.\nfunction gte(SD59x18 x, SD59x18 y) pure returns (bool result) {\n    result = x.unwrap() >= y.unwrap();\n}\n\n/// @notice Implements a zero comparison check function in the SD59x18 type.\nfunction isZero(SD59x18 x) pure returns (bool result) {\n    result = x.unwrap() == 0;\n}\n\n/// @notice Implements the left shift operation (<<) in the SD59x18 type.\nfunction lshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {\n    result = wrap(x.unwrap() << bits);\n}\n\n/// @notice Implements the lower than operation (<) in the SD59x18 type.\nfunction lt(SD59x18 x, SD59x18 y) pure returns (bool result) {\n    result = x.unwrap() < y.unwrap();\n}\n\n/// @notice Implements the lower than or equal to operation (<=) in the SD59x18 type.\nfunction lte(SD59x18 x, SD59x18 y) pure returns (bool result) {\n    result = x.unwrap() <= y.unwrap();\n}\n\n/// @notice Implements the unchecked modulo operation (%) in the SD59x18 type.\nfunction mod(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    result = wrap(x.unwrap() % y.unwrap());\n}\n\n/// @notice Implements the not equal operation (!=) in the SD59x18 type.\nfunction neq(SD59x18 x, SD59x18 y) pure returns (bool result) {\n    result = x.unwrap() != y.unwrap();\n}\n\n/// @notice Implements the NOT (~) bitwise operation in the SD59x18 type.\nfunction not(SD59x18 x) pure returns (SD59x18 result) {\n    result = wrap(~x.unwrap());\n}\n\n/// @notice Implements the OR (|) bitwise operation in the SD59x18 type.\nfunction or(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    result = wrap(x.unwrap() | y.unwrap());\n}\n\n/// @notice Implements the right shift operation (>>) in the SD59x18 type.\nfunction rshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {\n    result = wrap(x.unwrap() >> bits);\n}\n\n/// @notice Implements the checked subtraction operation (-) in the SD59x18 type.\nfunction sub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    result = wrap(x.unwrap() - y.unwrap());\n}\n\n/// @notice Implements the checked unary minus operation (-) in the SD59x18 type.\nfunction unary(SD59x18 x) pure returns (SD59x18 result) {\n    result = wrap(-x.unwrap());\n}\n\n/// @notice Implements the unchecked addition operation (+) in the SD59x18 type.\nfunction uncheckedAdd(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    unchecked {\n        result = wrap(x.unwrap() + y.unwrap());\n    }\n}\n\n/// @notice Implements the unchecked subtraction operation (-) in the SD59x18 type.\nfunction uncheckedSub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    unchecked {\n        result = wrap(x.unwrap() - y.unwrap());\n    }\n}\n\n/// @notice Implements the unchecked unary minus operation (-) in the SD59x18 type.\nfunction uncheckedUnary(SD59x18 x) pure returns (SD59x18 result) {\n    unchecked {\n        result = wrap(-x.unwrap());\n    }\n}\n\n/// @notice Implements the XOR (^) bitwise operation in the SD59x18 type.\nfunction xor(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    result = wrap(x.unwrap() ^ y.unwrap());\n}\n"
      },
      "lib/prb-math/src/sd59x18/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as Errors;\nimport {\n    uEXP_MAX_INPUT,\n    uEXP2_MAX_INPUT,\n    uHALF_UNIT,\n    uLOG2_10,\n    uLOG2_E,\n    uMAX_SD59x18,\n    uMAX_WHOLE_SD59x18,\n    uMIN_SD59x18,\n    uMIN_WHOLE_SD59x18,\n    UNIT,\n    uUNIT,\n    uUNIT_SQUARED,\n    ZERO\n} from \"./Constants.sol\";\nimport { wrap } from \"./Helpers.sol\";\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Calculates the absolute value of x.\n///\n/// @dev Requirements:\n/// - x must be greater than `MIN_SD59x18`.\n///\n/// @param x The SD59x18 number for which to calculate the absolute value.\n/// @param result The absolute value of x as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction abs(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    if (xInt == uMIN_SD59x18) {\n        revert Errors.PRBMath_SD59x18_Abs_MinSD59x18();\n    }\n    result = xInt < 0 ? wrap(-xInt) : x;\n}\n\n/// @notice Calculates the arithmetic average of x and y.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// @param x The first operand as an SD59x18 number.\n/// @param y The second operand as an SD59x18 number.\n/// @return result The arithmetic average as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction avg(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    int256 yInt = y.unwrap();\n\n    unchecked {\n        // This operation is equivalent to `x / 2 +  y / 2`, and it can never overflow.\n        int256 sum = (xInt >> 1) + (yInt >> 1);\n\n        if (sum < 0) {\n            // If at least one of x and y is odd, add 1 to the result, because shifting negative numbers to the right\n            // rounds toward negative infinity. The right part is equivalent to `sum + (x % 2 == 1 || y % 2 == 1)`.\n            assembly (\"memory-safe\") {\n                result := add(sum, and(or(xInt, yInt), 1))\n            }\n        } else {\n            // Add 1 if both x and y are odd to account for the double 0.5 remainder truncated after shifting.\n            result = wrap(sum + (xInt & yInt & 1));\n        }\n    }\n}\n\n/// @notice Yields the smallest whole number greater than or equal to x.\n///\n/// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts.\n/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n///\n/// Requirements:\n/// - x must be less than or equal to `MAX_WHOLE_SD59x18`.\n///\n/// @param x The SD59x18 number to ceil.\n/// @param result The smallest whole number greater than or equal to x, as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ceil(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    if (xInt > uMAX_WHOLE_SD59x18) {\n        revert Errors.PRBMath_SD59x18_Ceil_Overflow(x);\n    }\n\n    int256 remainder = xInt % uUNIT;\n    if (remainder == 0) {\n        result = x;\n    } else {\n        unchecked {\n            // Solidity uses C fmod style, which returns a modulus with the same sign as x.\n            int256 resultInt = xInt - remainder;\n            if (xInt > 0) {\n                resultInt += uUNIT;\n            }\n            result = wrap(resultInt);\n        }\n    }\n}\n\n/// @notice Divides two SD59x18 numbers, returning a new SD59x18 number.\n///\n/// @dev This is an extension of {Common.mulDiv} for signed numbers, which works by computing the signs and the absolute\n/// values separately.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv}.\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv}.\n/// - None of the inputs can be `MIN_SD59x18`.\n/// - The denominator must not be zero.\n/// - The result must fit in SD59x18.\n///\n/// @param x The numerator as an SD59x18 number.\n/// @param y The denominator as an SD59x18 number.\n/// @param result The quotient as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction div(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    int256 yInt = y.unwrap();\n    if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {\n        revert Errors.PRBMath_SD59x18_Div_InputTooSmall();\n    }\n\n    // Get hold of the absolute values of x and y.\n    uint256 xAbs;\n    uint256 yAbs;\n    unchecked {\n        xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);\n        yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);\n    }\n\n    // Compute the absolute value (x*UNIT÷y). The resulting value must fit in SD59x18.\n    uint256 resultAbs = Common.mulDiv(xAbs, uint256(uUNIT), yAbs);\n    if (resultAbs > uint256(uMAX_SD59x18)) {\n        revert Errors.PRBMath_SD59x18_Div_Overflow(x, y);\n    }\n\n    // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for\n    // negative, 0 for positive or zero).\n    bool sameSign = (xInt ^ yInt) > -1;\n\n    // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.\n    unchecked {\n        result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));\n    }\n}\n\n/// @notice Calculates the natural exponent of x using the following formula:\n///\n/// $$\n/// e^x = 2^{x * log_2{e}}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {exp2}.\n///\n/// Requirements:\n/// - Refer to the requirements in {exp2}.\n/// - x must be less than 133_084258667509499441.\n///\n/// @param x The exponent as an SD59x18 number.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n\n    // This check prevents values greater than 192e18 from being passed to {exp2}.\n    if (xInt > uEXP_MAX_INPUT) {\n        revert Errors.PRBMath_SD59x18_Exp_InputTooBig(x);\n    }\n\n    unchecked {\n        // Inline the fixed-point multiplication to save gas.\n        int256 doubleUnitProduct = xInt * uLOG2_E;\n        result = exp2(wrap(doubleUnitProduct / uUNIT));\n    }\n}\n\n/// @notice Calculates the binary exponent of x using the binary fraction method using the following formula:\n///\n/// $$\n/// 2^{-x} = \\frac{1}{2^x}\n/// $$\n///\n/// @dev See https://ethereum.stackexchange.com/q/79903/24693.\n///\n/// Notes:\n/// - If x is less than -59_794705707972522261, the result is zero.\n///\n/// Requirements:\n/// - x must be less than 192e18.\n/// - The result must fit in SD59x18.\n///\n/// @param x The exponent as an SD59x18 number.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction exp2(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    if (xInt < 0) {\n        // The inverse of any number less than this is truncated to zero.\n        if (xInt < -59_794705707972522261) {\n            return ZERO;\n        }\n\n        unchecked {\n            // Inline the fixed-point inversion to save gas.\n            result = wrap(uUNIT_SQUARED / exp2(wrap(-xInt)).unwrap());\n        }\n    } else {\n        // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format.\n        if (xInt > uEXP2_MAX_INPUT) {\n            revert Errors.PRBMath_SD59x18_Exp2_InputTooBig(x);\n        }\n\n        unchecked {\n            // Convert x to the 192.64-bit fixed-point format.\n            uint256 x_192x64 = uint256((xInt << 64) / uUNIT);\n\n            // It is safe to cast the result to int256 due to the checks above.\n            result = wrap(int256(Common.exp2(x_192x64)));\n        }\n    }\n}\n\n/// @notice Yields the greatest whole number less than or equal to x.\n///\n/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional\n/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n///\n/// Requirements:\n/// - x must be greater than or equal to `MIN_WHOLE_SD59x18`.\n///\n/// @param x The SD59x18 number to floor.\n/// @param result The greatest whole number less than or equal to x, as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction floor(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    if (xInt < uMIN_WHOLE_SD59x18) {\n        revert Errors.PRBMath_SD59x18_Floor_Underflow(x);\n    }\n\n    int256 remainder = xInt % uUNIT;\n    if (remainder == 0) {\n        result = x;\n    } else {\n        unchecked {\n            // Solidity uses C fmod style, which returns a modulus with the same sign as x.\n            int256 resultInt = xInt - remainder;\n            if (xInt < 0) {\n                resultInt -= uUNIT;\n            }\n            result = wrap(resultInt);\n        }\n    }\n}\n\n/// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right.\n/// of the radix point for negative numbers.\n/// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part\n/// @param x The SD59x18 number to get the fractional part of.\n/// @param result The fractional part of x as an SD59x18 number.\nfunction frac(SD59x18 x) pure returns (SD59x18 result) {\n    result = wrap(x.unwrap() % uUNIT);\n}\n\n/// @notice Calculates the geometric mean of x and y, i.e. $\\sqrt{x * y}$.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x * y must fit in SD59x18.\n/// - x * y must not be negative, since complex numbers are not supported.\n///\n/// @param x The first operand as an SD59x18 number.\n/// @param y The second operand as an SD59x18 number.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction gm(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    int256 yInt = y.unwrap();\n    if (xInt == 0 || yInt == 0) {\n        return ZERO;\n    }\n\n    unchecked {\n        // Equivalent to `xy / x != y`. Checking for overflow this way is faster than letting Solidity do it.\n        int256 xyInt = xInt * yInt;\n        if (xyInt / xInt != yInt) {\n            revert Errors.PRBMath_SD59x18_Gm_Overflow(x, y);\n        }\n\n        // The product must not be negative, since complex numbers are not supported.\n        if (xyInt < 0) {\n            revert Errors.PRBMath_SD59x18_Gm_NegativeProduct(x, y);\n        }\n\n        // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT`\n        // during multiplication. See the comments in {Common.sqrt}.\n        uint256 resultUint = Common.sqrt(uint256(xyInt));\n        result = wrap(int256(resultUint));\n    }\n}\n\n/// @notice Calculates the inverse of x.\n///\n/// @dev Notes:\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x must not be zero.\n///\n/// @param x The SD59x18 number for which to calculate the inverse.\n/// @return result The inverse as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction inv(SD59x18 x) pure returns (SD59x18 result) {\n    result = wrap(uUNIT_SQUARED / x.unwrap());\n}\n\n/// @notice Calculates the natural logarithm of x using the following formula:\n///\n/// $$\n/// ln{x} = log_2{x} / log_2{e}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n/// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The SD59x18 number for which to calculate the natural logarithm.\n/// @return result The natural logarithm as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction ln(SD59x18 x) pure returns (SD59x18 result) {\n    // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that\n    // {log2} can return is ~195_205294292027477728.\n    result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E);\n}\n\n/// @notice Calculates the common logarithm of x using the following formula:\n///\n/// $$\n/// log_{10}{x} = log_2{x} / log_2{10}\n/// $$\n///\n/// However, if x is an exact power of ten, a hard coded value is returned.\n///\n/// @dev Notes:\n/// - Refer to the notes in {log2}.\n///\n/// Requirements:\n/// - Refer to the requirements in {log2}.\n///\n/// @param x The SD59x18 number for which to calculate the common logarithm.\n/// @return result The common logarithm as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log10(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    if (xInt < 0) {\n        revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);\n    }\n\n    // Note that the `mul` in this block is the standard multiplication operation, not {SD59x18.mul}.\n    // prettier-ignore\n    assembly (\"memory-safe\") {\n        switch x\n        case 1 { result := mul(uUNIT, sub(0, 18)) }\n        case 10 { result := mul(uUNIT, sub(1, 18)) }\n        case 100 { result := mul(uUNIT, sub(2, 18)) }\n        case 1000 { result := mul(uUNIT, sub(3, 18)) }\n        case 10000 { result := mul(uUNIT, sub(4, 18)) }\n        case 100000 { result := mul(uUNIT, sub(5, 18)) }\n        case 1000000 { result := mul(uUNIT, sub(6, 18)) }\n        case 10000000 { result := mul(uUNIT, sub(7, 18)) }\n        case 100000000 { result := mul(uUNIT, sub(8, 18)) }\n        case 1000000000 { result := mul(uUNIT, sub(9, 18)) }\n        case 10000000000 { result := mul(uUNIT, sub(10, 18)) }\n        case 100000000000 { result := mul(uUNIT, sub(11, 18)) }\n        case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }\n        case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }\n        case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }\n        case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }\n        case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }\n        case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }\n        case 1000000000000000000 { result := 0 }\n        case 10000000000000000000 { result := uUNIT }\n        case 100000000000000000000 { result := mul(uUNIT, 2) }\n        case 1000000000000000000000 { result := mul(uUNIT, 3) }\n        case 10000000000000000000000 { result := mul(uUNIT, 4) }\n        case 100000000000000000000000 { result := mul(uUNIT, 5) }\n        case 1000000000000000000000000 { result := mul(uUNIT, 6) }\n        case 10000000000000000000000000 { result := mul(uUNIT, 7) }\n        case 100000000000000000000000000 { result := mul(uUNIT, 8) }\n        case 1000000000000000000000000000 { result := mul(uUNIT, 9) }\n        case 10000000000000000000000000000 { result := mul(uUNIT, 10) }\n        case 100000000000000000000000000000 { result := mul(uUNIT, 11) }\n        case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }\n        case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }\n        case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }\n        case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }\n        case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }\n        case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }\n        case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }\n        case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }\n        case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }\n        case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }\n        case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }\n        case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }\n        case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }\n        case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }\n        case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }\n        case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }\n        case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }\n        case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }\n        case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }\n        case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }\n        case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }\n        case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }\n        case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }\n        case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }\n        case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }\n        case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }\n        case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }\n        case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }\n        case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }\n        case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }\n        case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }\n        case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }\n        case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }\n        case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }\n        case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }\n        case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }\n        case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }\n        case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }\n        case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }\n        case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }\n        case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }\n        default { result := uMAX_SD59x18 }\n    }\n\n    if (result.unwrap() == uMAX_SD59x18) {\n        unchecked {\n            // Inline the fixed-point division to save gas.\n            result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10);\n        }\n    }\n}\n\n/// @notice Calculates the binary logarithm of x using the iterative approximation algorithm:\n///\n/// $$\n/// log_2{x} = n + log_2{y}, \\text{ where } y = x*2^{-n}, \\ y \\in [1, 2)\n/// $$\n///\n/// For $0 \\leq x \\lt 1$, the input is inverted:\n///\n/// $$\n/// log_2{x} = -log_2{\\frac{1}{x}}\n/// $$\n///\n/// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation.\n///\n/// Notes:\n/// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal.\n///\n/// Requirements:\n/// - x must be greater than zero.\n///\n/// @param x The SD59x18 number for which to calculate the binary logarithm.\n/// @return result The binary logarithm as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction log2(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    if (xInt <= 0) {\n        revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);\n    }\n\n    unchecked {\n        int256 sign;\n        if (xInt >= uUNIT) {\n            sign = 1;\n        } else {\n            sign = -1;\n            // Inline the fixed-point inversion to save gas.\n            xInt = uUNIT_SQUARED / xInt;\n        }\n\n        // Calculate the integer part of the logarithm.\n        uint256 n = Common.msb(uint256(xInt / uUNIT));\n\n        // This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow\n        // because n is at most 255, `UNIT` is 1e18, and the sign is either 1 or -1.\n        int256 resultInt = int256(n) * uUNIT;\n\n        // Calculate $y = x * 2^{-n}$.\n        int256 y = xInt >> n;\n\n        // If y is the unit number, the fractional part is zero.\n        if (y == uUNIT) {\n            return wrap(resultInt * sign);\n        }\n\n        // Calculate the fractional part via the iterative approximation.\n        // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient.\n        int256 DOUBLE_UNIT = 2e18;\n        for (int256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {\n            y = (y * y) / uUNIT;\n\n            // Is y^2 >= 2e18 and so in the range [2e18, 4e18)?\n            if (y >= DOUBLE_UNIT) {\n                // Add the 2^{-m} factor to the logarithm.\n                resultInt = resultInt + delta;\n\n                // Halve y, which corresponds to z/2 in the Wikipedia article.\n                y >>= 1;\n            }\n        }\n        resultInt *= sign;\n        result = wrap(resultInt);\n    }\n}\n\n/// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number.\n///\n/// @dev Notes:\n/// - Refer to the notes in {Common.mulDiv18}.\n///\n/// Requirements:\n/// - Refer to the requirements in {Common.mulDiv18}.\n/// - None of the inputs can be `MIN_SD59x18`.\n/// - The result must fit in SD59x18.\n///\n/// @param x The multiplicand as an SD59x18 number.\n/// @param y The multiplier as an SD59x18 number.\n/// @return result The product as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction mul(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    int256 yInt = y.unwrap();\n    if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {\n        revert Errors.PRBMath_SD59x18_Mul_InputTooSmall();\n    }\n\n    // Get hold of the absolute values of x and y.\n    uint256 xAbs;\n    uint256 yAbs;\n    unchecked {\n        xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);\n        yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);\n    }\n\n    // Compute the absolute value (x*y÷UNIT). The resulting value must fit in SD59x18.\n    uint256 resultAbs = Common.mulDiv18(xAbs, yAbs);\n    if (resultAbs > uint256(uMAX_SD59x18)) {\n        revert Errors.PRBMath_SD59x18_Mul_Overflow(x, y);\n    }\n\n    // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for\n    // negative, 0 for positive or zero).\n    bool sameSign = (xInt ^ yInt) > -1;\n\n    // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.\n    unchecked {\n        result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));\n    }\n}\n\n/// @notice Raises x to the power of y using the following formula:\n///\n/// $$\n/// x^y = 2^{log_2{x} * y}\n/// $$\n///\n/// @dev Notes:\n/// - Refer to the notes in {exp2}, {log2}, and {mul}.\n/// - Returns `UNIT` for 0^0.\n///\n/// Requirements:\n/// - Refer to the requirements in {exp2}, {log2}, and {mul}.\n///\n/// @param x The base as an SD59x18 number.\n/// @param y Exponent to raise x to, as an SD59x18 number\n/// @return result x raised to power y, as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction pow(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    int256 yInt = y.unwrap();\n\n    // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero.\n    if (xInt == 0) {\n        return yInt == 0 ? UNIT : ZERO;\n    }\n    // If x is `UNIT`, the result is always `UNIT`.\n    else if (xInt == uUNIT) {\n        return UNIT;\n    }\n\n    // If y is zero, the result is always `UNIT`.\n    if (yInt == 0) {\n        return UNIT;\n    }\n    // If y is `UNIT`, the result is always x.\n    else if (yInt == uUNIT) {\n        return x;\n    }\n\n    // Calculate the result using the formula.\n    result = exp2(mul(log2(x), y));\n}\n\n/// @notice Raises x (an SD59x18 number) to the power y (an unsigned basic integer) using the well-known\n/// algorithm \"exponentiation by squaring\".\n///\n/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring.\n///\n/// Notes:\n/// - Refer to the notes in {Common.mulDiv18}.\n/// - Returns `UNIT` for 0^0.\n///\n/// Requirements:\n/// - Refer to the requirements in {abs} and {Common.mulDiv18}.\n/// - The result must fit in SD59x18.\n///\n/// @param x The base as an SD59x18 number.\n/// @param y The exponent as a uint256.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction powu(SD59x18 x, uint256 y) pure returns (SD59x18 result) {\n    uint256 xAbs = uint256(abs(x).unwrap());\n\n    // Calculate the first iteration of the loop in advance.\n    uint256 resultAbs = y & 1 > 0 ? xAbs : uint256(uUNIT);\n\n    // Equivalent to `for(y /= 2; y > 0; y /= 2)`.\n    uint256 yAux = y;\n    for (yAux >>= 1; yAux > 0; yAux >>= 1) {\n        xAbs = Common.mulDiv18(xAbs, xAbs);\n\n        // Equivalent to `y % 2 == 1`.\n        if (yAux & 1 > 0) {\n            resultAbs = Common.mulDiv18(resultAbs, xAbs);\n        }\n    }\n\n    // The result must fit in SD59x18.\n    if (resultAbs > uint256(uMAX_SD59x18)) {\n        revert Errors.PRBMath_SD59x18_Powu_Overflow(x, y);\n    }\n\n    unchecked {\n        // Is the base negative and the exponent odd? If yes, the result should be negative.\n        int256 resultInt = int256(resultAbs);\n        bool isNegative = x.unwrap() < 0 && y & 1 == 1;\n        if (isNegative) {\n            resultInt = -resultInt;\n        }\n        result = wrap(resultInt);\n    }\n}\n\n/// @notice Calculates the square root of x using the Babylonian method.\n///\n/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n///\n/// Notes:\n/// - Only the positive root is returned.\n/// - The result is rounded toward zero.\n///\n/// Requirements:\n/// - x cannot be negative, since complex numbers are not supported.\n/// - x must be less than `MAX_SD59x18 / UNIT`.\n///\n/// @param x The SD59x18 number for which to calculate the square root.\n/// @return result The result as an SD59x18 number.\n/// @custom:smtchecker abstract-function-nondet\nfunction sqrt(SD59x18 x) pure returns (SD59x18 result) {\n    int256 xInt = x.unwrap();\n    if (xInt < 0) {\n        revert Errors.PRBMath_SD59x18_Sqrt_NegativeInput(x);\n    }\n    if (xInt > uMAX_SD59x18 / uUNIT) {\n        revert Errors.PRBMath_SD59x18_Sqrt_Overflow(x);\n    }\n\n    unchecked {\n        // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two SD59x18 numbers.\n        // In this case, the two numbers are both the square root.\n        uint256 resultUint = Common.sqrt(uint256(xInt * uUNIT));\n        result = wrap(int256(resultUint));\n    }\n}\n"
      },
      "lib/prb-math/src/ud2x18/Casting.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport \"../Common.sol\" as Common;\nimport \"./Errors.sol\" as Errors;\nimport { uMAX_SD1x18 } from \"../sd1x18/Constants.sol\";\nimport { SD1x18 } from \"../sd1x18/ValueType.sol\";\nimport { SD59x18 } from \"../sd59x18/ValueType.sol\";\nimport { UD2x18 } from \"../ud2x18/ValueType.sol\";\nimport { UD60x18 } from \"../ud60x18/ValueType.sol\";\nimport { UD2x18 } from \"./ValueType.sol\";\n\n/// @notice Casts a UD2x18 number into SD1x18.\n/// - x must be less than or equal to `uMAX_SD1x18`.\nfunction intoSD1x18(UD2x18 x) pure returns (SD1x18 result) {\n    uint64 xUint = UD2x18.unwrap(x);\n    if (xUint > uint64(uMAX_SD1x18)) {\n        revert Errors.PRBMath_UD2x18_IntoSD1x18_Overflow(x);\n    }\n    result = SD1x18.wrap(int64(xUint));\n}\n\n/// @notice Casts a UD2x18 number into SD59x18.\n/// @dev There is no overflow check because the domain of UD2x18 is a subset of SD59x18.\nfunction intoSD59x18(UD2x18 x) pure returns (SD59x18 result) {\n    result = SD59x18.wrap(int256(uint256(UD2x18.unwrap(x))));\n}\n\n/// @notice Casts a UD2x18 number into UD60x18.\n/// @dev There is no overflow check because the domain of UD2x18 is a subset of UD60x18.\nfunction intoUD60x18(UD2x18 x) pure returns (UD60x18 result) {\n    result = UD60x18.wrap(UD2x18.unwrap(x));\n}\n\n/// @notice Casts a UD2x18 number into uint128.\n/// @dev There is no overflow check because the domain of UD2x18 is a subset of uint128.\nfunction intoUint128(UD2x18 x) pure returns (uint128 result) {\n    result = uint128(UD2x18.unwrap(x));\n}\n\n/// @notice Casts a UD2x18 number into uint256.\n/// @dev There is no overflow check because the domain of UD2x18 is a subset of uint256.\nfunction intoUint256(UD2x18 x) pure returns (uint256 result) {\n    result = uint256(UD2x18.unwrap(x));\n}\n\n/// @notice Casts a UD2x18 number into uint40.\n/// @dev Requirements:\n/// - x must be less than or equal to `MAX_UINT40`.\nfunction intoUint40(UD2x18 x) pure returns (uint40 result) {\n    uint64 xUint = UD2x18.unwrap(x);\n    if (xUint > uint64(Common.MAX_UINT40)) {\n        revert Errors.PRBMath_UD2x18_IntoUint40_Overflow(x);\n    }\n    result = uint40(xUint);\n}\n\n/// @notice Alias for {wrap}.\nfunction ud2x18(uint64 x) pure returns (UD2x18 result) {\n    result = UD2x18.wrap(x);\n}\n\n/// @notice Unwrap a UD2x18 number into uint64.\nfunction unwrap(UD2x18 x) pure returns (uint64 result) {\n    result = UD2x18.unwrap(x);\n}\n\n/// @notice Wraps a uint64 number into UD2x18.\nfunction wrap(uint64 x) pure returns (UD2x18 result) {\n    result = UD2x18.wrap(x);\n}\n"
      },
      "lib/prb-math/src/sd1x18/Errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD1x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD2x18.\nerror PRBMath_SD1x18_ToUD2x18_Underflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD60x18.\nerror PRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint128.\nerror PRBMath_SD1x18_ToUint128_Underflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint256.\nerror PRBMath_SD1x18_ToUint256_Underflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40.\nerror PRBMath_SD1x18_ToUint40_Overflow(SD1x18 x);\n\n/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40.\nerror PRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);\n"
      },
      "lib/prb-math/src/sd59x18/Errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { SD59x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when taking the absolute value of `MIN_SD59x18`.\nerror PRBMath_SD59x18_Abs_MinSD59x18();\n\n/// @notice Thrown when ceiling a number overflows SD59x18.\nerror PRBMath_SD59x18_Ceil_Overflow(SD59x18 x);\n\n/// @notice Thrown when converting a basic integer to the fixed-point format overflows SD59x18.\nerror PRBMath_SD59x18_Convert_Overflow(int256 x);\n\n/// @notice Thrown when converting a basic integer to the fixed-point format underflows SD59x18.\nerror PRBMath_SD59x18_Convert_Underflow(int256 x);\n\n/// @notice Thrown when dividing two numbers and one of them is `MIN_SD59x18`.\nerror PRBMath_SD59x18_Div_InputTooSmall();\n\n/// @notice Thrown when dividing two numbers and one of the intermediary unsigned results overflows SD59x18.\nerror PRBMath_SD59x18_Div_Overflow(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441.\nerror PRBMath_SD59x18_Exp_InputTooBig(SD59x18 x);\n\n/// @notice Thrown when taking the binary exponent of a base greater than 192e18.\nerror PRBMath_SD59x18_Exp2_InputTooBig(SD59x18 x);\n\n/// @notice Thrown when flooring a number underflows SD59x18.\nerror PRBMath_SD59x18_Floor_Underflow(SD59x18 x);\n\n/// @notice Thrown when taking the geometric mean of two numbers and their product is negative.\nerror PRBMath_SD59x18_Gm_NegativeProduct(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows SD59x18.\nerror PRBMath_SD59x18_Gm_Overflow(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18.\nerror PRBMath_SD59x18_IntoSD1x18_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18.\nerror PRBMath_SD59x18_IntoSD1x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18.\nerror PRBMath_SD59x18_IntoUD2x18_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18.\nerror PRBMath_SD59x18_IntoUD2x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD60x18.\nerror PRBMath_SD59x18_IntoUD60x18_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128.\nerror PRBMath_SD59x18_IntoUint128_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128.\nerror PRBMath_SD59x18_IntoUint128_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint256.\nerror PRBMath_SD59x18_IntoUint256_Underflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40.\nerror PRBMath_SD59x18_IntoUint40_Overflow(SD59x18 x);\n\n/// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40.\nerror PRBMath_SD59x18_IntoUint40_Underflow(SD59x18 x);\n\n/// @notice Thrown when taking the logarithm of a number less than or equal to zero.\nerror PRBMath_SD59x18_Log_InputTooSmall(SD59x18 x);\n\n/// @notice Thrown when multiplying two numbers and one of the inputs is `MIN_SD59x18`.\nerror PRBMath_SD59x18_Mul_InputTooSmall();\n\n/// @notice Thrown when multiplying two numbers and the intermediary absolute result overflows SD59x18.\nerror PRBMath_SD59x18_Mul_Overflow(SD59x18 x, SD59x18 y);\n\n/// @notice Thrown when raising a number to a power and hte intermediary absolute result overflows SD59x18.\nerror PRBMath_SD59x18_Powu_Overflow(SD59x18 x, uint256 y);\n\n/// @notice Thrown when taking the square root of a negative number.\nerror PRBMath_SD59x18_Sqrt_NegativeInput(SD59x18 x);\n\n/// @notice Thrown when the calculating the square root overflows SD59x18.\nerror PRBMath_SD59x18_Sqrt_Overflow(SD59x18 x);\n"
      },
      "lib/prb-math/src/ud2x18/Errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19;\n\nimport { UD2x18 } from \"./ValueType.sol\";\n\n/// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in SD1x18.\nerror PRBMath_UD2x18_IntoSD1x18_Overflow(UD2x18 x);\n\n/// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in uint40.\nerror PRBMath_UD2x18_IntoUint40_Overflow(UD2x18 x);\n"
      }
    },
    "settings": {
      "remappings": [
        "rain.metadata/=lib/rain.metadata/src/",
        "@prb/test/=lib/prb-math/lib/prb-test/src/",
        "bytecode/=lib/rain.interpreter.interface/src/lib/bytecode/",
        "caller/=lib/rain.interpreter.interface/src/lib/caller/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "ns/=lib/rain.interpreter.interface/src/lib/ns/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "prb-math/=lib/prb-math/src/",
        "prb-test/=lib/prb-math/lib/prb-test/src/",
        "rain.chainlink/=lib/rain.chainlink/src/",
        "rain.datacontract/=lib/rain.datacontract/src/",
        "rain.erc1820/=lib/rain.erc1820/src/",
        "rain.interpreter.interface/=lib/rain.interpreter.interface/src/",
        "rain.intorastring/=lib/rain.intorastring/",
        "rain.lib.hash/=lib/rain.lib.memkv/lib/rain.lib.hash/src/",
        "rain.lib.memkv/=lib/rain.lib.memkv/src/",
        "rain.lib.typecast/=lib/rain.lib.typecast/src/",
        "rain.math.fixedpoint/=lib/rain.math.fixedpoint/src/",
        "rain.math.saturating/=lib/rain.math.saturating/src/",
        "rain.solmem/=lib/rain.solmem/src/",
        "sol.lib.binmaskflag/=lib/sol.lib.binmaskflag/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": false
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}