creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/concrete/UniswapWords.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {\n    UniswapExtern,\n    OPCODE_FUNCTION_POINTERS,\n    INTEGRITY_FUNCTION_POINTERS,\n    BaseRainterpreterExternNPE2,\n    UniswapExternConfig\n} from \"../abstract/UniswapExtern.sol\";\nimport {\n    UniswapSubParser,\n    SUB_PARSER_WORD_PARSERS,\n    SUB_PARSER_OPERAND_HANDLERS,\n    SUB_PARSER_PARSE_META,\n    SUB_PARSER_LITERAL_PARSERS,\n    BaseRainterpreterSubParserNPE2,\n    AuthoringMetaV2,\n    authoringMetaV2\n} from \"../abstract/UniswapSubParser.sol\";\n\n/// @title UniswapWords\n/// Simply merges the two abstract contracts into a single concrete contract.\ncontract UniswapWords is UniswapExtern, UniswapSubParser {\n    constructor(UniswapExternConfig memory externConfig) UniswapExtern(externConfig) {}\n\n    /// @inheritdoc UniswapSubParser\n    //slither-disable-next-line dead-code\n    function extern() internal view override returns (address) {\n        return address(this);\n    }\n\n    /// This is only needed because the parser and extern base contracts both\n    /// implement IERC165, and the compiler needs to be told how to resolve the\n    /// ambiguity.\n    /// @inheritdoc BaseRainterpreterSubParserNPE2\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        virtual\n        override(BaseRainterpreterSubParserNPE2, BaseRainterpreterExternNPE2)\n        returns (bool)\n    {\n        return super.supportsInterface(interfaceId);\n    }\n}\n"
      },
      "src/abstract/UniswapExtern.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {BaseRainterpreterExternNPE2, Operand} from \"rain.interpreter/abstract/BaseRainterpreterExternNPE2.sol\";\nimport {LibConvert} from \"rain.lib.typecast/LibConvert.sol\";\nimport {OpUniswapV2AmountIn} from \"./op/OpUniswapV2AmountIn.sol\";\nimport {OpUniswapV2AmountOut} from \"./op/OpUniswapV2AmountOut.sol\";\nimport {OpUniswapV2Quote} from \"./op/OpUniswapV2Quote.sol\";\nimport {OpUniswapV3ExactOutput} from \"./op/OpUniswapV3ExactOutput.sol\";\nimport {OpUniswapV3ExactInput} from \"./op/OpUniswapV3ExactInput.sol\";\nimport {OpUniswapV3Twap} from \"./op/OpUniswapV3Twap.sol\";\nimport {IViewQuoterV3} from \"../interface/IViewQuoterV3.sol\";\n\n/// @dev Runtime constant form of the pointers to the integrity functions.\nbytes constant INTEGRITY_FUNCTION_POINTERS = hex\"173e173e174e175e175e176a\";\n/// @dev Runtime constant form of the pointers to the opcode functions.\nbytes constant OPCODE_FUNCTION_POINTERS = hex\"0df10e640eab1018113311f2\";\n\n/// @dev Index into the function pointers array for the V2 amount in.\nuint256 constant OPCODE_UNISWAP_V2_AMOUNT_IN = 0;\n/// @dev Index into the function pointers array for the V2 amount out.\nuint256 constant OPCODE_UNISWAP_V2_AMOUNT_OUT = 1;\n/// @dev Index into the function pointers array for the V2 quote.\nuint256 constant OPCODE_UNISWAP_V2_QUOTE = 2;\n/// @dev Index into the function pointers array for the V3 exact output.\nuint256 constant OPCODE_UNISWAP_V3_EXACT_OUTPUT = 3;\n/// @dev Index into the function pointers array for the V3 exact input.\nuint256 constant OPCODE_UNISWAP_V3_EXACT_INPUT = 4;\n/// @dev Index into the function pointers array for the V3 twap.\nuint256 constant OPCODE_UNISWAP_V3_TWAP = 5;\n/// @dev The number of function pointers in the array.\nuint256 constant OPCODE_FUNCTION_POINTERS_LENGTH = 6;\n\nstruct UniswapExternConfig {\n    address v2Factory;\n    address v3Quoter;\n}\n\n/// @title UniswapExtern\n/// Implements externs for Uniswap V2 and V3.\nabstract contract UniswapExtern is\n    BaseRainterpreterExternNPE2,\n    OpUniswapV2AmountIn,\n    OpUniswapV2AmountOut,\n    OpUniswapV2Quote,\n    OpUniswapV3ExactOutput,\n    OpUniswapV3ExactInput,\n    OpUniswapV3Twap\n{\n    address public immutable iV2Factory;\n    address public immutable iV3Factory;\n    IViewQuoterV3 public immutable iV3Quoter;\n\n    constructor(UniswapExternConfig memory config) {\n        iV2Factory = config.v2Factory;\n        iV3Quoter = IViewQuoterV3(config.v3Quoter);\n        iV3Factory = iV3Quoter.factory();\n    }\n\n    /// @inheritdoc OpUniswapV2AmountIn\n    //slither-disable-next-line dead-code\n    function v2Factory()\n        internal\n        view\n        override(OpUniswapV2AmountIn, OpUniswapV2AmountOut, OpUniswapV2Quote)\n        returns (address)\n    {\n        return iV2Factory;\n    }\n\n    /// @inheritdoc OpUniswapV3Twap\n    //slither-disable-next-line dead-code\n    function v3Factory() internal view override returns (address) {\n        return iV3Factory;\n    }\n\n    /// @inheritdoc OpUniswapV3ExactOutput\n    //slither-disable-next-line dead-code\n    function v3Quoter() internal view override(OpUniswapV3ExactOutput, OpUniswapV3ExactInput) returns (IViewQuoterV3) {\n        return iV3Quoter;\n    }\n\n    /// @inheritdoc BaseRainterpreterExternNPE2\n    function opcodeFunctionPointers() internal pure override returns (bytes memory) {\n        return OPCODE_FUNCTION_POINTERS;\n    }\n\n    /// @inheritdoc BaseRainterpreterExternNPE2\n    function integrityFunctionPointers() internal pure override returns (bytes memory) {\n        return INTEGRITY_FUNCTION_POINTERS;\n    }\n\n    /// Create a 16-bit pointer array for the opcode function pointers. This is\n    /// relatively gas inefficent so it is only called during tests to cross\n    /// reference against the constant values that are used at runtime.\n    function buildOpcodeFunctionPointers() external pure returns (bytes memory) {\n        function(Operand, uint256[] memory) internal view returns (uint256[] memory)[] memory fs = new function(Operand, uint256[] memory) internal view returns (uint256[] memory)[](\n            OPCODE_FUNCTION_POINTERS_LENGTH\n        );\n        fs[OPCODE_UNISWAP_V2_AMOUNT_IN] = OpUniswapV2AmountIn.runUniswapV2AmountIn;\n        fs[OPCODE_UNISWAP_V2_AMOUNT_OUT] = OpUniswapV2AmountOut.runUniswapV2AmountOut;\n        fs[OPCODE_UNISWAP_V2_QUOTE] = OpUniswapV2Quote.runUniswapV2Quote;\n        fs[OPCODE_UNISWAP_V3_EXACT_OUTPUT] = OpUniswapV3ExactOutput.runUniswapV3ExactOutput;\n        fs[OPCODE_UNISWAP_V3_EXACT_INPUT] = OpUniswapV3ExactInput.runUniswapV3ExactInput;\n        fs[OPCODE_UNISWAP_V3_TWAP] = OpUniswapV3Twap.runUniswapV3Twap;\n\n        uint256[] memory pointers;\n        assembly (\"memory-safe\") {\n            pointers := fs\n        }\n        return LibConvert.unsafeTo16BitBytes(pointers);\n    }\n\n    /// Create a 16-bit pointer array for the integrity function pointers. This\n    /// is relatively gas inefficent so it is only called during tests to cross\n    /// reference against the constant values that are used at runtime.\n    function buildIntegrityFunctionPointers() external pure returns (bytes memory) {\n        function(Operand, uint256, uint256) internal pure returns (uint256, uint256)[] memory fs = new function(Operand, uint256, uint256) internal pure returns (uint256, uint256)[](\n            OPCODE_FUNCTION_POINTERS_LENGTH\n        );\n        fs[OPCODE_UNISWAP_V2_AMOUNT_IN] = OpUniswapV2AmountIn.integrityUniswapV2AmountIn;\n        fs[OPCODE_UNISWAP_V2_AMOUNT_OUT] = OpUniswapV2AmountOut.integrityUniswapV2AmountOut;\n        fs[OPCODE_UNISWAP_V2_QUOTE] = OpUniswapV2Quote.integrityUniswapV2Quote;\n        fs[OPCODE_UNISWAP_V3_EXACT_OUTPUT] = OpUniswapV3ExactOutput.integrityUniswapV3ExactOutput;\n        fs[OPCODE_UNISWAP_V3_EXACT_INPUT] = OpUniswapV3ExactInput.integrityUniswapV3ExactInput;\n        fs[OPCODE_UNISWAP_V3_TWAP] = OpUniswapV3Twap.integrityUniswapV3Twap;\n\n        uint256[] memory pointers;\n        assembly (\"memory-safe\") {\n            pointers := fs\n        }\n        return LibConvert.unsafeTo16BitBytes(pointers);\n    }\n}\n"
      },
      "src/abstract/UniswapSubParser.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {BaseRainterpreterSubParserNPE2, Operand} from \"rain.interpreter/abstract/BaseRainterpreterSubParserNPE2.sol\";\nimport {LibSubParse, IInterpreterExternV3} from \"rain.interpreter/lib/parse/LibSubParse.sol\";\nimport {LibParseOperand} from \"rain.interpreter/lib/parse/LibParseOperand.sol\";\nimport {LibConvert} from \"rain.lib.typecast/LibConvert.sol\";\nimport {AuthoringMetaV2} from \"rain.interpreter/interface/IParserV1.sol\";\nimport {\n    OPCODE_UNISWAP_V2_AMOUNT_IN,\n    OPCODE_UNISWAP_V2_AMOUNT_OUT,\n    OPCODE_UNISWAP_V2_QUOTE,\n    OPCODE_UNISWAP_V3_EXACT_OUTPUT,\n    OPCODE_UNISWAP_V3_EXACT_INPUT,\n    OPCODE_UNISWAP_V3_TWAP\n} from \"./UniswapExtern.sol\";\n\n/// @dev Runtime constant form of the parse meta. Used to map stringy words into\n/// indexes in roughly O(1).\nbytes constant SUB_PARSER_PARSE_META =\n    hex\"010000000000040000000000008800000000020000a0000000000000000000000000059852a103fd758204722c3102fe814f01b519ad007b1e62\";\n\n/// @dev Runtime constant form of the pointers to the word parsers.\nbytes constant SUB_PARSER_WORD_PARSERS = hex\"0cdf0d010d140d270d3a0d4d\";\n\n/// @dev Runtime constant form of the pointers to the operand handlers.\nbytes constant SUB_PARSER_OPERAND_HANDLERS = hex\"16641664166416f916f916f9\";\n\n/// @dev Runtime constant form of the pointers to the literal parsers.\nbytes constant SUB_PARSER_LITERAL_PARSERS = hex\"165b\";\n\n/// @dev Index into the function pointers array for the V2 amount in.\nuint256 constant SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_IN = 0;\n/// @dev Index into the function pointers array for the V2 amount out.\nuint256 constant SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_OUT = 1;\n/// @dev Index into the function pointers array for the V2 quote.\nuint256 constant SUB_PARSER_WORD_UNISWAP_V2_QUOTE = 2;\n/// @dev Index into the function pointers array for the V3 exact output.\nuint256 constant SUB_PARSER_WORD_UNISWAP_V3_EXACT_OUTPUT = 3;\n/// @dev Index into the function pointers array for the V3 exact input.\nuint256 constant SUB_PARSER_WORD_UNISWAP_V3_EXACT_INPUT = 4;\n/// @dev Index into the function pointers array for the V3 twap.\nuint256 constant SUB_PARSER_WORD_UNISWAP_V3_TWAP = 5;\n/// @dev The number of function pointers in the array.\nuint256 constant SUB_PARSER_WORD_PARSERS_LENGTH = 6;\n\n/// Builds the authoring meta for the sub parser. This is used both as data for\n/// tooling directly, and to build the runtime parse meta.\n//slither-disable-next-line dead-code\nfunction authoringMetaV2() pure returns (bytes memory) {\n    AuthoringMetaV2[] memory meta = new AuthoringMetaV2[](SUB_PARSER_WORD_PARSERS_LENGTH);\n    meta[SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_IN] = AuthoringMetaV2(\n        \"uniswap-v2-quote-exact-output\",\n        \"Quotes the minimum absolute amount of input tokens required to get a given amount of output tokens from a Uniswap V2 pair. Input/output token directions are from the perspective of the Uniswap pool contract. The first input is the input token address, the second is the output token address, and the third is the amount of output tokens. If the operand is 1 the last time the prices changed will be returned as well.\"\n    );\n    meta[SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_OUT] = AuthoringMetaV2(\n        \"uniswap-v2-quote-exact-input\",\n        \"Computes the maximum amount of output tokens received from a given amount of input tokens from a Uniswap V2 pair. Input/output token directions are from the perspective of the Uniswap pool contract. The first input is the input token address, the second is the output token address, and the third is the amount of input tokens. If the operand is 1 the last time the prices changed will be returned as well.\"\n    );\n    meta[SUB_PARSER_WORD_UNISWAP_V2_QUOTE] = AuthoringMetaV2(\n        \"uniswap-v2-spot-output-ratio\",\n        \"The current instantaneous \\\"spot\\\" output ratio (output per unit of input) of a given token pair. Input/output token directions are from the perspective of the Uniswap pool contract. The first and second inputs are the input token address and decimals, the third and fourth are the output token address and decimals. If the operand is 1 the last time the ratio changed will be returned as well.\"\n    );\n    meta[SUB_PARSER_WORD_UNISWAP_V3_EXACT_OUTPUT] = AuthoringMetaV2(\n        \"uniswap-v3-quote-exact-output\",\n        \"Quotes the minimum absolute amount of input tokens required to get a given exact amount of output tokens from a Uniswap V3 pair. Input/output token directions are from the perspective of the Uniswap pool contract. The first input is the input token address, the second is the output token address, the third is the exact output amount, and the fourth is the pool fee.\"\n    );\n    meta[SUB_PARSER_WORD_UNISWAP_V3_EXACT_INPUT] = AuthoringMetaV2(\n        \"uniswap-v3-quote-exact-input\",\n        \"Quotes the maximum amount of output tokens received from a given amount of input tokens from a Uniswap V3 pair. Input/output token directions are from the perspective of the Uniswap pool contract. The first input is the input token address, the second is the output token address, the third is the exact input amount, and the fourth is the pool fee.\"\n    );\n    meta[SUB_PARSER_WORD_UNISWAP_V3_TWAP] = AuthoringMetaV2(\n        \"uniswap-v3-twap-output-ratio\",\n        \"The time weighted average output ratio (output per unit of input) of a given token pair over a given period of time, as an 18 decimal fixed point ratio. Input/output token directions are from the perspective of the Uniswap pool contract. The first and second inputs are the input token address and decimals, the third and fourth are the output token address and decimals, the fifth and sixth are the start and end times ago in seconds, and the seventh is the pool fee. If the start and end times are both 0, returns the current instantaneous \\\"spot\\\" ratio rather than an average. Note that uniswap TWAP prices suffer lossy compression as they are converted to/from \\\"ticks\\\" so are only accurate to within 0.01%.\"\n    );\n    return abi.encode(meta);\n}\n\nuint256 constant SUB_PARSER_LITERAL_UNISWAP_V3_FEE_INDEX = 0;\n\n/// @dev The literal string for the high fee UniswapV3 pool.\nbytes constant LITERAL_UNISWAP_V3_FEE_HIGH = \"uniswap-v3-fee-high\";\nuint256 constant LITERAL_UNISWAP_V3_FEE_HIGH_LENGTH = 19;\nuint256 constant LITERAL_UNISWAP_V3_FEE_HIGH_MASK = ~((1 << ((0x20 - LITERAL_UNISWAP_V3_FEE_HIGH_LENGTH) * 8)) - 1);\n/// @dev The value that is returned when the high fee UniswapV3 pool is used.\n/// https://docs.uniswap.org/sdk/v3/reference/enums/FeeAmount#high\nuint256 constant LITERAL_UNISWAP_V3_FEE_HIGH_VALUE = 10000;\n\n/// @dev The literal string for the medium fee UniswapV3 pool.\nbytes constant LITERAL_UNISWAP_V3_FEE_MEDIUM = \"uniswap-v3-fee-medium\";\nuint256 constant LITERAL_UNISWAP_V3_FEE_MEDIUM_LENGTH = 21;\nuint256 constant LITERAL_UNISWAP_V3_FEE_MEDIUM_MASK = ~((1 << ((0x20 - LITERAL_UNISWAP_V3_FEE_MEDIUM_LENGTH) * 8)) - 1);\n/// @dev The value that is returned when the medium fee UniswapV3 pool is used.\n/// https://docs.uniswap.org/sdk/v3/reference/enums/FeeAmount#medium\nuint256 constant LITERAL_UNISWAP_V3_FEE_MEDIUM_VALUE = 3000;\n\n/// @dev The literal string for the low fee UniswapV3 pool.\nbytes constant LITERAL_UNISWAP_V3_FEE_LOW = \"uniswap-v3-fee-low\";\nuint256 constant LITERAL_UNISWAP_V3_FEE_LOW_LENGTH = 18;\nuint256 constant LITERAL_UNISWAP_V3_FEE_LOW_MASK = ~((1 << ((0x20 - LITERAL_UNISWAP_V3_FEE_LOW_LENGTH) * 8)) - 1);\n/// @dev The value that is returned when the low fee UniswapV3 pool is used.\n/// https://docs.uniswap.org/sdk/v3/reference/enums/FeeAmount#low\nuint256 constant LITERAL_UNISWAP_V3_FEE_LOW_VALUE = 500;\n\n/// @dev The literal string for the lowest fee UniswapV3 pool.\nbytes constant LITERAL_UNISWAP_V3_FEE_LOWEST = \"uniswap-v3-fee-lowest\";\nuint256 constant LITERAL_UNISWAP_V3_FEE_LOWEST_LENGTH = 21;\nuint256 constant LITERAL_UNISWAP_V3_FEE_LOWEST_MASK = ~((1 << ((0x20 - LITERAL_UNISWAP_V3_FEE_LOWEST_LENGTH) * 8)) - 1);\n/// @dev The value that is returned when the lowest fee UniswapV3 pool is used.\n/// https://docs.uniswap.org/sdk/v3/reference/enums/FeeAmount#lowest\nuint256 constant LITERAL_UNISWAP_V3_FEE_LOWEST_VALUE = 100;\n\n/// @title UniswapSubParser\n/// Implements the sub parser half of UniswapWords. Responsible for parsing\n/// the words and operands that are used by the UniswapWords. Provides the\n/// sugar required to make the externs work like native rain words.\nabstract contract UniswapSubParser is BaseRainterpreterSubParserNPE2 {\n    /// Allows the UniswapWords contract to feed the extern address (itself)\n    /// into the sub parser functions by overriding `extern`.\n    function extern() internal view virtual returns (address);\n\n    /// @inheritdoc BaseRainterpreterSubParserNPE2\n    function subParserParseMeta() internal pure override returns (bytes memory) {\n        return SUB_PARSER_PARSE_META;\n    }\n\n    //slither-disable-next-line dead-code\n    function parseUniswapV3Fee(uint256 value, uint256, uint256) internal pure returns (uint256) {\n        return value;\n    }\n\n    /// Overrides the base literal parsers for sub parsing. Simply returns the\n    /// known constant value, which should allow the compiler to optimise the\n    /// entire function call away.\n    function subParserLiteralParsers() internal pure override returns (bytes memory) {\n        return SUB_PARSER_LITERAL_PARSERS;\n    }\n\n    function buildSubParserLiteralParsers() external pure returns (bytes memory) {\n        unchecked {\n            function (uint256, uint256, uint256) internal pure returns (uint256)[] memory fs =\n                new function (uint256, uint256, uint256) internal pure returns (uint256)[](1);\n            fs[SUB_PARSER_LITERAL_UNISWAP_V3_FEE_INDEX] = parseUniswapV3Fee;\n\n            uint256[] memory pointers;\n            assembly (\"memory-safe\") {\n                pointers := fs\n            }\n            return LibConvert.unsafeTo16BitBytes(pointers);\n        }\n    }\n\n    function matchSubParseLiteralDispatch(uint256 cursor, uint256 end)\n        internal\n        pure\n        virtual\n        override\n        returns (bool, uint256, uint256)\n    {\n        uint256 loaded;\n        assembly (\"memory-safe\") {\n            loaded := mload(cursor)\n        }\n        if (\n            end - cursor == bytes(LITERAL_UNISWAP_V3_FEE_HIGH).length\n                && loaded & LITERAL_UNISWAP_V3_FEE_HIGH_MASK == uint256(bytes32(LITERAL_UNISWAP_V3_FEE_HIGH))\n        ) {\n            return (true, SUB_PARSER_LITERAL_UNISWAP_V3_FEE_INDEX, LITERAL_UNISWAP_V3_FEE_HIGH_VALUE);\n        } else if (\n            end - cursor == bytes(LITERAL_UNISWAP_V3_FEE_MEDIUM).length\n                && loaded & LITERAL_UNISWAP_V3_FEE_MEDIUM_MASK == uint256(bytes32(LITERAL_UNISWAP_V3_FEE_MEDIUM))\n        ) {\n            return (true, SUB_PARSER_LITERAL_UNISWAP_V3_FEE_INDEX, LITERAL_UNISWAP_V3_FEE_MEDIUM_VALUE);\n        } else if (\n            end - cursor == bytes(LITERAL_UNISWAP_V3_FEE_LOW).length\n                && loaded & LITERAL_UNISWAP_V3_FEE_LOW_MASK == uint256(bytes32(LITERAL_UNISWAP_V3_FEE_LOW))\n        ) {\n            return (true, SUB_PARSER_LITERAL_UNISWAP_V3_FEE_INDEX, LITERAL_UNISWAP_V3_FEE_LOW_VALUE);\n        } else if (\n            end - cursor == bytes(LITERAL_UNISWAP_V3_FEE_LOWEST).length\n                && loaded & LITERAL_UNISWAP_V3_FEE_LOWEST_MASK == uint256(bytes32(LITERAL_UNISWAP_V3_FEE_LOWEST))\n        ) {\n            return (true, SUB_PARSER_LITERAL_UNISWAP_V3_FEE_INDEX, LITERAL_UNISWAP_V3_FEE_LOWEST_VALUE);\n        } else {\n            return (false, 0, 0);\n        }\n    }\n\n    /// @inheritdoc BaseRainterpreterSubParserNPE2\n    function subParserWordParsers() internal pure override returns (bytes memory) {\n        return SUB_PARSER_WORD_PARSERS;\n    }\n\n    /// @inheritdoc BaseRainterpreterSubParserNPE2\n    function subParserOperandHandlers() internal pure override returns (bytes memory) {\n        return SUB_PARSER_OPERAND_HANDLERS;\n    }\n\n    /// Create a 16-bit pointer array for the operand handlers. This is\n    /// relatively gas inefficent so it is only called during tests to cross\n    /// reference against the constant values that are used at runtime.\n    function buildSubParserOperandHandlers() external pure returns (bytes memory) {\n        function(uint256[] memory) internal pure returns (Operand)[] memory fs =\n            new function(uint256[] memory) internal pure returns (Operand)[](SUB_PARSER_WORD_PARSERS_LENGTH);\n        fs[SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_IN] = LibParseOperand.handleOperandSingleFull;\n        fs[SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_OUT] = LibParseOperand.handleOperandSingleFull;\n        fs[SUB_PARSER_WORD_UNISWAP_V2_QUOTE] = LibParseOperand.handleOperandSingleFull;\n        fs[SUB_PARSER_WORD_UNISWAP_V3_EXACT_OUTPUT] = LibParseOperand.handleOperandDisallowed;\n        fs[SUB_PARSER_WORD_UNISWAP_V3_EXACT_INPUT] = LibParseOperand.handleOperandDisallowed;\n        fs[SUB_PARSER_WORD_UNISWAP_V3_TWAP] = LibParseOperand.handleOperandDisallowed;\n\n        uint256[] memory pointers;\n        assembly (\"memory-safe\") {\n            pointers := fs\n        }\n        return LibConvert.unsafeTo16BitBytes(pointers);\n    }\n\n    /// Create a 16-bit pointer array for the word parsers. This is relatively\n    /// gas inefficent so it is only called during tests to cross reference\n    /// against the constant values that are used at runtime.\n    function buildSubParserWordParsers() external pure returns (bytes memory) {\n        function(uint256, uint256, Operand) internal view returns (bool, bytes memory, uint256[] memory)[] memory fs =\n        new function(uint256, uint256, Operand) internal view returns (bool, bytes memory, uint256[] memory)[](\n            SUB_PARSER_WORD_PARSERS_LENGTH\n        );\n        fs[SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_IN] = uniswapV2AmountInSubParser;\n        fs[SUB_PARSER_WORD_UNISWAP_V2_AMOUNT_OUT] = uniswapV2AmountOutSubParser;\n        fs[SUB_PARSER_WORD_UNISWAP_V2_QUOTE] = uniswapV2QuoteSubParser;\n        fs[SUB_PARSER_WORD_UNISWAP_V3_EXACT_OUTPUT] = uniswapV3ExactOutputSubParser;\n        fs[SUB_PARSER_WORD_UNISWAP_V3_EXACT_INPUT] = uniswapV3ExactInputSubParser;\n        fs[SUB_PARSER_WORD_UNISWAP_V3_TWAP] = uniswapV3TwapSubParser;\n\n        uint256[] memory pointers;\n        assembly (\"memory-safe\") {\n            pointers := fs\n        }\n        return LibConvert.unsafeTo16BitBytes(pointers);\n    }\n\n    /// Thin wrapper around LibSubParse.subParserExtern that provides the extern\n    /// address and index of the amount in opcode index in the extern.\n    //slither-disable-next-line dead-code\n    function uniswapV2AmountInSubParser(uint256 constantsHeight, uint256 ioByte, Operand operand)\n        internal\n        view\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        //slither-disable-next-line unused-return\n        return LibSubParse.subParserExtern(\n            IInterpreterExternV3(extern()), constantsHeight, ioByte, operand, OPCODE_UNISWAP_V2_AMOUNT_IN\n        );\n    }\n\n    /// Thin wrapper around LibSubParse.subParserExtern that provides the extern\n    /// address and index of the amount out opcode index in the extern.\n    //slither-disable-next-line dead-code\n    function uniswapV2AmountOutSubParser(uint256 constantsHeight, uint256 ioByte, Operand operand)\n        internal\n        view\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        //slither-disable-next-line unused-return\n        return LibSubParse.subParserExtern(\n            IInterpreterExternV3(extern()), constantsHeight, ioByte, operand, OPCODE_UNISWAP_V2_AMOUNT_OUT\n        );\n    }\n\n    /// Thin wrapper around LibSubParse.subParserExtern that provides the extern\n    /// address and index of the quote opcode index in the extern.\n    //slither-disable-next-line dead-code\n    function uniswapV2QuoteSubParser(uint256 constantsHeight, uint256 ioByte, Operand operand)\n        internal\n        view\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        //slither-disable-next-line unused-return\n        return LibSubParse.subParserExtern(\n            IInterpreterExternV3(extern()), constantsHeight, ioByte, operand, OPCODE_UNISWAP_V2_QUOTE\n        );\n    }\n\n    /// Thin wrapper around LibSubParse.subParserExtern that provides the extern\n    /// address and index of the exact output opcode index in the extern.\n    //slither-disable-next-line dead-code\n    function uniswapV3ExactOutputSubParser(uint256 constantsHeight, uint256 ioByte, Operand operand)\n        internal\n        view\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        //slither-disable-next-line unused-return\n        return LibSubParse.subParserExtern(\n            IInterpreterExternV3(extern()), constantsHeight, ioByte, operand, OPCODE_UNISWAP_V3_EXACT_OUTPUT\n        );\n    }\n\n    /// Thin wrapper around LibSubParse.subParserExtern that provides the extern\n    /// address and index of the exact input opcode index in the extern.\n    //slither-disable-next-line dead-code\n    function uniswapV3ExactInputSubParser(uint256 constantsHeight, uint256 ioByte, Operand operand)\n        internal\n        view\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        //slither-disable-next-line unused-return\n        return LibSubParse.subParserExtern(\n            IInterpreterExternV3(extern()), constantsHeight, ioByte, operand, OPCODE_UNISWAP_V3_EXACT_INPUT\n        );\n    }\n\n    /// Thin wrapper around LibSubParse.subParserExtern that provides the extern\n    /// address and index of the TWAP opcode index in the extern.\n    //slither-disable-next-line dead-code\n    function uniswapV3TwapSubParser(uint256 constantsHeight, uint256 ioByte, Operand operand)\n        internal\n        view\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        //slither-disable-next-line unused-return\n        return LibSubParse.subParserExtern(\n            IInterpreterExternV3(extern()), constantsHeight, ioByte, operand, OPCODE_UNISWAP_V3_TWAP\n        );\n    }\n}\n"
      },
      "lib/rain.interpreter/src/abstract/BaseRainterpreterExternNPE2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {ERC165} from \"openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\n\nimport {BadInputs} from \"../error/ErrExtern.sol\";\nimport {Pointer} from \"rain.solmem/lib/LibPointer.sol\";\nimport {LibStackPointer} from \"rain.solmem/lib/LibStackPointer.sol\";\nimport {LibUint256Array} from \"rain.solmem/lib/LibUint256Array.sol\";\n\nimport {Operand} from \"../interface/unstable/IInterpreterV2.sol\";\nimport {IInterpreterExternV3, ExternDispatch} from \"../interface/unstable/IInterpreterExternV3.sol\";\n\n/// @dev Empty opcode function pointers constant. Inheriting contracts should\n/// create their own constant and override `opcodeFunctionPointers` to use\n/// theirs.\nbytes constant OPCODE_FUNCTION_POINTERS = hex\"\";\n/// @dev Empty integrity function pointers constant. Inheriting contracts should\n/// create their own constant and override `integrityFunctionPointers` to use\n/// theirs.\nbytes constant INTEGRITY_FUNCTION_POINTERS = hex\"\";\n\n/// Base implementation of `IInterpreterExternV3`. Inherit from this contract,\n/// and override `functionPointers` to provide a list of function pointers.\nabstract contract BaseRainterpreterExternNPE2 is IInterpreterExternV3, ERC165 {\n    using LibStackPointer for uint256[];\n    using LibStackPointer for Pointer;\n    using LibUint256Array for uint256;\n    using LibUint256Array for uint256[];\n\n    /// @inheritdoc IInterpreterExternV3\n    function extern(ExternDispatch dispatch, uint256[] memory inputs)\n        external\n        view\n        virtual\n        override\n        returns (uint256[] memory outputs)\n    {\n        unchecked {\n            bytes memory fPointers = opcodeFunctionPointers();\n            uint256 fsCount = fPointers.length / 2;\n            uint256 fPointersStart;\n            assembly (\"memory-safe\") {\n                fPointersStart := add(fPointers, 0x20)\n            }\n            uint256 opcode = (ExternDispatch.unwrap(dispatch) >> 0x10) & type(uint16).max;\n            Operand operand = Operand.wrap(ExternDispatch.unwrap(dispatch) & type(uint16).max);\n\n            function(Operand, uint256[] memory) internal view returns (uint256[] memory) f;\n            assembly {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(opcode, fsCount), 2))))\n            }\n            outputs = f(operand, inputs);\n        }\n    }\n\n    /// @inheritdoc IInterpreterExternV3\n    function externIntegrity(ExternDispatch dispatch, uint256 expectedInputs, uint256 expectedOutputs)\n        external\n        pure\n        virtual\n        override\n        returns (uint256 actualInputs, uint256 actualOutputs)\n    {\n        unchecked {\n            bytes memory fPointers = integrityFunctionPointers();\n            uint256 fsCount = fPointers.length / 2;\n            uint256 fPointersStart;\n            assembly (\"memory-safe\") {\n                fPointersStart := add(fPointers, 0x20)\n            }\n            uint256 opcode = (ExternDispatch.unwrap(dispatch) >> 0x10) & type(uint16).max;\n            Operand operand = Operand.wrap(ExternDispatch.unwrap(dispatch) & type(uint16).max);\n\n            function(Operand, uint256, uint256) internal pure returns (uint256, uint256) f;\n            assembly {\n                f := shr(0xf0, mload(add(fPointersStart, mul(mod(opcode, fsCount), 2))))\n            }\n            (actualInputs, actualOutputs) = f(operand, expectedInputs, expectedOutputs);\n        }\n    }\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IInterpreterExternV3).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /// Overrideable function to provide the list of function pointers for\n    /// word dispatches.\n    //slither-disable-next-line dead-code\n    function opcodeFunctionPointers() internal view virtual returns (bytes memory) {\n        return OPCODE_FUNCTION_POINTERS;\n    }\n\n    /// Overrideable function to provide the list of function pointers for\n    /// integrity checks.\n    //slither-disable-next-line dead-code\n    function integrityFunctionPointers() internal pure virtual returns (bytes memory) {\n        return INTEGRITY_FUNCTION_POINTERS;\n    }\n}\n"
      },
      "lib/rain.interpreter/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/abstract/op/OpUniswapV2AmountIn.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter/interface/unstable/IInterpreterV2.sol\";\nimport {LibUniswapV2} from \"../../lib/LibUniswapV2.sol\";\n\n/// @title OpUniswapV2AmountIn\n/// @notice Opcode to calculate the amount in for a Uniswap V2 pair.\nabstract contract OpUniswapV2AmountIn {\n    function v2Factory() internal view virtual returns (address);\n\n    /// Extern integrity for the process of calculating the amount in for a\n    /// Uniswap V2 pair. Always requires 3 inputs and produces 1 or 2 outputs.\n    //slither-disable-next-line dead-code\n    function integrityUniswapV2AmountIn(Operand operand, uint256, uint256) internal pure returns (uint256, uint256) {\n        unchecked {\n            // Outputs is 1 if we don't want the timestamp (operand 0) or 2 if we\n            // do (operand 1).\n            uint256 outputs = 1 + (Operand.unwrap(operand) & 1);\n            return (3, outputs);\n        }\n    }\n\n    //slither-disable-next-line dead-code\n    function runUniswapV2AmountIn(Operand operand, uint256[] memory inputs) internal view returns (uint256[] memory) {\n        uint256 tokenIn;\n        uint256 tokenOut;\n        uint256 amountOut;\n        uint256 withTime;\n        assembly (\"memory-safe\") {\n            tokenIn := mload(add(inputs, 0x20))\n            tokenOut := mload(add(inputs, 0x40))\n            amountOut := mload(add(inputs, 0x60))\n            withTime := and(operand, 1)\n        }\n        (uint256 amountIn, uint256 reserveTimestamp) = LibUniswapV2.getAmountInByTokenWithTime(\n            v2Factory(), address(uint160(tokenIn)), address(uint160(tokenOut)), amountOut\n        );\n\n        assembly (\"memory-safe\") {\n            mstore(inputs, 1)\n            mstore(add(inputs, 0x20), amountIn)\n            if withTime {\n                mstore(inputs, 2)\n                mstore(add(inputs, 0x40), reserveTimestamp)\n            }\n        }\n        return inputs;\n    }\n\n    // function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n    //     internal\n    //     view\n    //     returns (uint256[] memory outputs)\n    // {\n    //     uint256 factory = inputs[0];\n    //     uint256 amountOut = inputs[1];\n    //     uint256 tokenIn = inputs[2];\n    //     uint256 tokenOut = inputs[3];\n    //     (uint256 amountIn, uint256 reserveTimestamp) = LibUniswapV2.getAmountInByTokenWithTime(\n    //         address(uint160(factory)), address(uint160(tokenIn)), address(uint160(tokenOut)), amountOut\n    //     );\n    //     outputs = new uint256[](1 + (Operand.unwrap(operand) & 1));\n    //     outputs[0] = amountIn;\n    //     if (Operand.unwrap(operand) & 1 == 1) outputs[1] = reserveTimestamp;\n    // }\n}\n"
      },
      "src/abstract/op/OpUniswapV2AmountOut.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {LibUniswapV2} from \"../../lib/LibUniswapV2.sol\";\nimport {Operand} from \"rain.interpreter/interface/unstable/IInterpreterV2.sol\";\n\n/// @title OpUniswapV2AmountOut\n/// @notice Opcode to calculate the amount out for a Uniswap V2 pair.\nabstract contract OpUniswapV2AmountOut {\n    function v2Factory() internal view virtual returns (address);\n\n    /// Extern integrity for the process of calculating the amount out for a\n    /// Uniswap V2 pair. Always requires 3 inputs and produces 1 or 2 outputs.\n    //slither-disable-next-line dead-code\n    function integrityUniswapV2AmountOut(Operand operand, uint256, uint256) internal pure returns (uint256, uint256) {\n        unchecked {\n            // Outputs is 1 if we don't want the timestamp (operand 0) or 2 if we\n            // do (operand 1).\n            uint256 outputs = 1 + (Operand.unwrap(operand) & 1);\n            return (3, outputs);\n        }\n    }\n\n    //slither-disable-next-line dead-code\n    function runUniswapV2AmountOut(Operand operand, uint256[] memory inputs) internal view returns (uint256[] memory) {\n        uint256 tokenIn;\n        uint256 tokenOut;\n        uint256 amountIn;\n        uint256 withTime;\n        assembly (\"memory-safe\") {\n            tokenIn := mload(add(inputs, 0x20))\n            tokenOut := mload(add(inputs, 0x40))\n            amountIn := mload(add(inputs, 0x60))\n            withTime := and(operand, 1)\n        }\n        (uint256 amountOut, uint256 reserveTimestamp) = LibUniswapV2.getAmountOutByTokenWithTime(\n            v2Factory(), address(uint160(tokenIn)), address(uint160(tokenOut)), amountIn\n        );\n\n        assembly (\"memory-safe\") {\n            mstore(inputs, 1)\n            mstore(add(inputs, 0x20), amountOut)\n            if withTime {\n                mstore(inputs, 2)\n                mstore(add(inputs, 0x40), reserveTimestamp)\n            }\n        }\n        return inputs;\n    }\n\n    // function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n    //     internal\n    //     view\n    //     returns (uint256[] memory outputs)\n    // {\n    //     uint256 factory = inputs[0];\n    //     uint256 amountIn = inputs[1];\n    //     uint256 tokenIn = inputs[2];\n    //     uint256 tokenOut = inputs[3];\n    //     (uint256 amountOut, uint256 reserveTimestamp) = LibUniswapV2.getAmountOutByTokenWithTime(\n    //         address(uint160(factory)), address(uint160(tokenIn)), address(uint160(tokenOut)), amountIn\n    //     );\n    //     outputs = new uint256[](1 + (Operand.unwrap(operand) & 1));\n    //     outputs[0] = amountOut;\n    //     if (Operand.unwrap(operand) & 1 == 1) outputs[1] = reserveTimestamp;\n    // }\n}\n"
      },
      "src/abstract/op/OpUniswapV2Quote.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter/interface/unstable/IInterpreterV2.sol\";\nimport {LibUniswapV2} from \"../../lib/LibUniswapV2.sol\";\nimport {LibFixedPointDecimalScale} from \"rain.math.fixedpoint/lib/LibFixedPointDecimalScale.sol\";\n\nerror UniswapV2TwapTokenDecimalsOverflow(address token, uint256 decimals);\nerror UniswapV2TwapTokenOrder(uint256 tokenIn, uint256 tokenOut);\n\n/// @title OpUniswapV2Quote\n/// @notice Opcode to calculate the quote for a Uniswap V2 pair.\nabstract contract OpUniswapV2Quote {\n    function v2Factory() internal view virtual returns (address);\n\n    /// Extern integrity for the process of calculating the quote for a Uniswap\n    /// V2 pair. Always requires 3 inputs and produces 1 or 2 outputs.\n    //slither-disable-next-line dead-code\n    function integrityUniswapV2Quote(Operand operand, uint256, uint256) internal pure returns (uint256, uint256) {\n        unchecked {\n            // Outputs is 1 if we don't want the timestamp (operand 0) or 2 if we\n            // do (operand 1).\n            uint256 outputs = 1 + (Operand.unwrap(operand) & 1);\n            return (4, outputs);\n        }\n    }\n\n    //slither-disable-next-line dead-code\n    function runUniswapV2Quote(Operand operand, uint256[] memory inputs) internal view returns (uint256[] memory) {\n        uint256 tokenIn;\n        uint256 tokenInDecimals;\n        uint256 tokenOut;\n        uint256 tokenOutDecimals;\n        uint256 withTime;\n        assembly (\"memory-safe\") {\n            tokenIn := mload(add(inputs, 0x20))\n            tokenInDecimals := mload(add(inputs, 0x40))\n            tokenOut := mload(add(inputs, 0x60))\n            tokenOutDecimals := mload(add(inputs, 0x80))\n            withTime := and(operand, 1)\n        }\n        // The output ratio is the amount of tokenOut per tokenIn. If we get a\n        // quote for 1e18 tokenIn, the amount out is the 18 decimal ratio.\n        //\n        // However, the two tokens may have significantly different decimals. If\n        // we only ask for 1e18, and the decimals are very different, we'll end\n        // up with precision loss when we rescale the output ratio below. By\n        // asking for 1e36, we can rescale the output ratio to 18 decimals\n        // then divide by 1e18 to get the correct amount out with full precision.\n        (uint256 amountOut, uint256 reserveTimestamp) =\n            LibUniswapV2.getQuoteWithTime(v2Factory(), address(uint160(tokenIn)), address(uint160(tokenOut)), 1e36);\n\n        // Scale the amountOut to 18 decimal fixed point ratio, according to each\n        // token's decimals.\n        {\n            if (tokenInDecimals > uint256(uint8(type(int8).max))) {\n                revert UniswapV2TwapTokenDecimalsOverflow(address(uint160(tokenIn)), tokenInDecimals);\n            }\n\n            if (tokenOutDecimals > uint256(uint8(type(int8).max))) {\n                revert UniswapV2TwapTokenDecimalsOverflow(address(uint160(tokenOut)), tokenOutDecimals);\n            }\n\n            amountOut = LibFixedPointDecimalScale.scaleBy(\n                amountOut, int8(uint8(tokenInDecimals)) - int8(uint8(tokenOutDecimals)), 0\n            );\n        }\n\n        amountOut /= 1e18;\n\n        assembly (\"memory-safe\") {\n            mstore(inputs, 1)\n            mstore(add(inputs, 0x20), amountOut)\n            if withTime {\n                mstore(inputs, 2)\n                mstore(add(inputs, 0x40), reserveTimestamp)\n            }\n        }\n        return inputs;\n    }\n\n    // function referenceFn(InterpreterStateNP memory, Operand operand, uint256[] memory inputs)\n    //     internal\n    //     view\n    //     returns (uint256[] memory outputs)\n    // {\n    //     uint256 factory = inputs[0];\n    //     uint256 amountA = inputs[1];\n    //     uint256 tokenA = inputs[2];\n    //     uint256 tokenB = inputs[3];\n    //     (uint256 amountB, uint256 reserveTimestamp) = LibUniswapV2.getQuoteWithTime(\n    //         address(uint160(factory)), address(uint160(tokenA)), address(uint160(tokenB)), amountA\n    //     );\n    //     outputs = new uint256[](1 + (Operand.unwrap(operand) & 1));\n    //     outputs[0] = amountB;\n    //     if (Operand.unwrap(operand) & 1 == 1) {\n    //         outputs[1] = reserveTimestamp;\n    //     }\n    // }\n}\n"
      },
      "src/abstract/op/OpUniswapV3ExactOutput.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter/interface/unstable/IInterpreterV2.sol\";\nimport {IViewQuoterV3} from \"../../interface/IViewQuoterV3.sol\";\n\n/// @title OpUniswapV3ExactOutput\n/// @notice Opcode to calculate the amount in for an exact output from a Uniswap\n/// V3 pair.\nabstract contract OpUniswapV3ExactOutput {\n    function v3Quoter() internal view virtual returns (IViewQuoterV3);\n\n    //slither-disable-next-line dead-code\n    function integrityUniswapV3ExactOutput(Operand, uint256, uint256) internal pure returns (uint256, uint256) {\n        return (4, 1);\n    }\n\n    //slither-disable-next-line dead-code\n    function runUniswapV3ExactOutput(Operand, uint256[] memory inputs) internal view returns (uint256[] memory) {\n        uint256 tokenIn;\n        uint256 tokenOut;\n        uint256 amountOut;\n        uint256 fee;\n        assembly (\"memory-safe\") {\n            tokenIn := mload(add(inputs, 0x20))\n            tokenOut := mload(add(inputs, 0x40))\n            amountOut := mload(add(inputs, 0x60))\n            fee := mload(add(inputs, 0x80))\n        }\n        (uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate) = v3Quoter()\n            .quoteExactOutputSingle(\n            IViewQuoterV3.QuoteExactOutputSingleParams(\n                address(uint160(tokenIn)),\n                address(uint160(tokenOut)),\n                amountOut,\n                uint24(fee),\n                // This is the sqrtPriceLimitX96, which is 0 for no limit.\n                // It's not even used by the quoter contract internally.\n                0\n            )\n        );\n        (sqrtPriceX96After, initializedTicksCrossed, gasEstimate);\n        assembly (\"memory-safe\") {\n            mstore(inputs, 1)\n            mstore(add(inputs, 0x20), amountIn)\n        }\n        return inputs;\n    }\n}\n"
      },
      "src/abstract/op/OpUniswapV3ExactInput.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter/interface/unstable/IInterpreterV2.sol\";\nimport {IViewQuoterV3} from \"../../interface/IViewQuoterV3.sol\";\n\n/// @title OpUniswapV3ExactInput\n/// @notice Opcode to calculate the amount in for an exact input from a Uniswap\n/// V3 pair.\nabstract contract OpUniswapV3ExactInput {\n    function v3Quoter() internal view virtual returns (IViewQuoterV3);\n\n    //slither-disable-next-line dead-code\n    function integrityUniswapV3ExactInput(Operand, uint256, uint256) internal pure returns (uint256, uint256) {\n        return (4, 1);\n    }\n\n    //slither-disable-next-line dead-code\n    function runUniswapV3ExactInput(Operand, uint256[] memory inputs) internal view returns (uint256[] memory) {\n        uint256 tokenIn;\n        uint256 tokenOut;\n        uint256 amountIn;\n        uint256 fee;\n        assembly (\"memory-safe\") {\n            tokenIn := mload(add(inputs, 0x20))\n            tokenOut := mload(add(inputs, 0x40))\n            amountIn := mload(add(inputs, 0x60))\n            fee := mload(add(inputs, 0x80))\n        }\n        (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate) = v3Quoter()\n            .quoteExactInputSingle(\n            IViewQuoterV3.QuoteExactInputSingleParams(\n                address(uint160(tokenIn)),\n                address(uint160(tokenOut)),\n                amountIn,\n                uint24(fee),\n                // This is the sqrtPriceLimitX96, which is 0 for no limit.\n                // It's not even used by the quoter contract internally.\n                0\n            )\n        );\n        (sqrtPriceX96After, initializedTicksCrossed, gasEstimate);\n        assembly (\"memory-safe\") {\n            mstore(inputs, 1)\n            mstore(add(inputs, 0x20), amountOut)\n        }\n        return inputs;\n    }\n}\n"
      },
      "src/abstract/op/OpUniswapV3Twap.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand} from \"rain.interpreter/interface/unstable/IInterpreterV2.sol\";\nimport {LibUniswapV3PoolAddress} from \"../../lib/v3/LibUniswapV3PoolAddress.sol\";\nimport {IUniswapV3Pool} from \"v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {LibUniswapV3TickMath} from \"../../lib/v3/LibUniswapV3TickMath.sol\";\nimport {FixedPoint96} from \"v3-core/contracts/libraries/FixedPoint96.sol\";\nimport {Math} from \"openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport {LibFixedPointDecimalScale} from \"rain.math.fixedpoint/lib/LibFixedPointDecimalScale.sol\";\n\nerror UniswapV3TwapStartAfterEnd(uint256 startSecondsAgo, uint256 endSecondsAgo);\nerror UniswapV3TwapTokenOrder(uint256 tokenIn, uint256 tokenOut);\nerror UniswapV3TwapTokenDecimalsOverflow(address token, uint256 decimals);\n\n/// @title OpUniswapV3Twap\n/// @notice Opcode to calculate the average ratio of a token pair over a period\n/// of time according to the uniswap v3 twap.\nabstract contract OpUniswapV3Twap {\n    function v3Factory() internal view virtual returns (address);\n\n    //slither-disable-next-line dead-code\n    function integrityUniswapV3Twap(Operand, uint256, uint256) internal pure returns (uint256, uint256) {\n        return (7, 1);\n    }\n\n    //slither-disable-next-line dead-code\n    function runUniswapV3Twap(Operand, uint256[] memory inputs) internal view returns (uint256[] memory) {\n        uint256 tokenIn;\n        uint256 tokenInDecimals;\n        uint256 tokenOut;\n        uint256 tokenOutDecimals;\n        uint256 startSecondsAgo;\n        uint256 endSecondsAgo;\n        uint256 fee;\n        assembly (\"memory-safe\") {\n            tokenIn := mload(add(inputs, 0x20))\n            tokenInDecimals := mload(add(inputs, 0x40))\n            tokenOut := mload(add(inputs, 0x60))\n            tokenOutDecimals := mload(add(inputs, 0x80))\n            startSecondsAgo := mload(add(inputs, 0xa0))\n            endSecondsAgo := mload(add(inputs, 0xc0))\n            fee := mload(add(inputs, 0xe0))\n        }\n\n        if (startSecondsAgo < endSecondsAgo) {\n            revert UniswapV3TwapStartAfterEnd(startSecondsAgo, endSecondsAgo);\n        }\n\n        IUniswapV3Pool pool = IUniswapV3Pool(\n            LibUniswapV3PoolAddress.computeAddress(\n                v3Factory(),\n                LibUniswapV3PoolAddress.getPoolKey(address(uint160(tokenIn)), address(uint160(tokenOut)), uint24(fee))\n            )\n        );\n\n        uint160 sqrtPriceX96;\n\n        // Start 0 means current price.\n        if (startSecondsAgo == 0) {\n            //slither-disable-next-line unused-return\n            (sqrtPriceX96,,,,,,) = pool.slot0();\n        } else {\n            uint32[] memory secondsAgos = new uint32[](2);\n            secondsAgos[0] = uint32(startSecondsAgo);\n            secondsAgos[1] = uint32(endSecondsAgo);\n            //slither-disable-next-line unused-return\n            (int56[] memory tickCumulatives,) = pool.observe(secondsAgos);\n\n            sqrtPriceX96 = LibUniswapV3TickMath.getSqrtRatioAtTick(\n                int24((tickCumulatives[1] - tickCumulatives[0]) / int56(uint56(startSecondsAgo - endSecondsAgo)))\n            );\n        }\n\n        // The sqrt price is always token0/token1, so if the tokens are in the\n        // wrong order, we need to invert the sqrt price.\n        if (tokenOut <= tokenIn) {\n            sqrtPriceX96 = uint160(uint256(2 ** 192) / sqrtPriceX96);\n        }\n\n        // `uint256(type(uint160).max) * 1e18` doesn't overflow, so this can't\n        // either.\n        // We rely on the compiler to optimise the 2 ** 192 out.\n        //\n        // Math:\n        // sqrtPriceX96 = sqrt(price) * 2 ** 96\n        // => sqrtPriceX96 / 2 ** 96 = sqrt(price)\n        // => (sqrtPriceX96 / 2 ** 96) ** 2 = price\n        // => (sqrtPriceX96 ** 2) / (2 ** 96) ** 2 = price\n        // => (sqrtPriceX96 ** 2) / (2 ** 192) = price\n        //\n        // The above math results in an integer ratio, so `5` literally\n        // represents that the ratio is `5:1`. This is generally useless because\n        // it is incapable of representing decimals. In fact, all sub-1 prices\n        // are simply rounded to 0. To avoid this we multiply by 1e18, which\n        // gives us 18 decimal fixed point math version of the same, such that\n        // `5e18` represents `5:1` and `5e17` represents `0.5:1`.\n        //\n        // Note that the tokens themselves may have different decimals.\n        // For example, weth has 18 decimals, while usdc has 6, which leads to\n        // ratios that are 12 ooms away from 18. Normalising all ratios to 18\n        // regardless of the token decimals gives us a consistent representation\n        // of \"price\" as a ratio, even though it's useless for actual token\n        // movements.\n        //\n        // When we divide by 2 ** 192, we can lose a lot of precision, that we\n        // MAY want to keep if the token decimals are very different. For this\n        // reason we scale the twap up by an additional 1e18 here, and then\n        // rescale according to the token decimals, then remove the additional\n        // 1e18 scaling at the end.\n        uint256 twap = Math.mulDiv(uint256(sqrtPriceX96) * 1e18, uint256(sqrtPriceX96) * 1e18, 2 ** 192);\n\n        // Scale the twap to 18 decimal fixed point ratio, according to each\n        // token's decimals.\n        {\n            if (tokenInDecimals > uint256(uint8(type(int8).max))) {\n                revert UniswapV3TwapTokenDecimalsOverflow(address(uint160(tokenIn)), tokenInDecimals);\n            }\n\n            if (tokenOutDecimals > uint256(uint8(type(int8).max))) {\n                revert UniswapV3TwapTokenDecimalsOverflow(address(uint160(tokenOut)), tokenOutDecimals);\n            }\n\n            twap =\n                LibFixedPointDecimalScale.scaleBy(twap, int8(uint8(tokenInDecimals)) - int8(uint8(tokenOutDecimals)), 0);\n        }\n\n        // Remove the additional 1e18 scaling we did above in the mulDiv.\n        twap /= 1e18;\n\n        assembly (\"memory-safe\") {\n            mstore(inputs, 1)\n            mstore(add(inputs, 0x20), twap)\n        }\n        return inputs;\n    }\n}\n"
      },
      "src/interface/IViewQuoterV3.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// IViewQuoterV3 is IQuoter but view\ninterface IViewQuoterV3 {\n    /// This is on the Quoter contract even though it isn't in the upstream\n    /// interface.\n    function factory() external view returns (address);\n\n    /// IQuoter.quoteExactInput but view\n    function quoteExactInput(bytes memory path, uint256 amountIn)\n        external\n        view\n        returns (\n            uint256 amountOut,\n            uint160[] memory sqrtPriceX96AfterList,\n            uint32[] memory initializedTicksCrossedList,\n            uint256 gasEstimate\n        );\n\n    struct QuoteExactInputSingleWithPoolParams {\n        address tokenIn;\n        address tokenOut;\n        uint256 amountIn;\n        address pool;\n        uint24 fee;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// IQuoter.quoteExactInputSingleWithPool but view\n    function quoteExactInputSingleWithPool(QuoteExactInputSingleWithPoolParams memory params)\n        external\n        view\n        returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate);\n\n    struct QuoteExactInputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint256 amountIn;\n        uint24 fee;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// IQuoter.quoteExactInputSingle but view\n    function quoteExactInputSingle(QuoteExactInputSingleParams memory params)\n        external\n        view\n        returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate);\n\n    struct QuoteExactOutputSingleWithPoolParams {\n        address tokenIn;\n        address tokenOut;\n        uint256 amount;\n        uint24 fee;\n        address pool;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// IQuoter.quoteExactOutputSingleWithPool but view\n    function quoteExactOutputSingleWithPool(QuoteExactOutputSingleWithPoolParams memory params)\n        external\n        view\n        returns (uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate);\n\n    struct QuoteExactOutputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint256 amount;\n        uint24 fee;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// IQuoter.quoteExactOutputSingle but view\n    function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params)\n        external\n        view\n        returns (uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate);\n\n    /// IQuoter.quoteExactOutput but view\n    function quoteExactOutput(bytes memory path, uint256 amountOut)\n        external\n        view\n        returns (\n            uint256 amountIn,\n            uint160[] memory sqrtPriceX96AfterList,\n            uint32[] memory initializedTicksCrossedList,\n            uint256 gasEstimate\n        );\n}\n"
      },
      "lib/rain.interpreter/src/abstract/BaseRainterpreterSubParserNPE2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity =0.8.19;\n\nimport {ERC165} from \"openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\nimport {LibBytes, Pointer} from \"rain.solmem/lib/LibBytes.sol\";\n\nimport {ISubParserV2, COMPATIBLITY_V3} from \"../interface/unstable/ISubParserV2.sol\";\nimport {IncompatibleSubParser} from \"../error/ErrSubParse.sol\";\nimport {LibSubParse, ParseState} from \"../lib/parse/LibSubParse.sol\";\nimport {CMASK_RHS_WORD_TAIL} from \"../lib/parse/LibParseCMask.sol\";\nimport {LibParse, Operand} from \"../lib/parse/LibParse.sol\";\nimport {LibParseMeta} from \"../lib/parse/LibParseMeta.sol\";\nimport {LibParseOperand} from \"../lib/parse/LibParseOperand.sol\";\n\n/// @dev This is a placeholder for the subparser function pointers.\n/// The subparser function pointers are a list of 16 bit function pointers,\n/// where each subparser function is responsible for parsing a particular\n/// word into a an opcode that will be used by the main parser to build the\n/// final bytecode.\nbytes constant SUB_PARSER_WORD_PARSERS = hex\"\";\n\n/// @dev This is a placeholder for the subparser meta bytes.\n/// The subparser meta bytes are the same structure as the main parser meta\n/// bytes. The exact same process of hashing, blooming, fingeprinting and index\n/// lookup applies to the subparser meta bytes as the main parser meta bytes.\nbytes constant SUB_PARSER_PARSE_META = hex\"\";\n\n/// @dev This is a placeholder for the int that encodes pointers to operand\n/// parsers.\nbytes constant SUB_PARSER_OPERAND_HANDLERS = hex\"\";\n\n/// @dev This is a placeholder for the int that encodes pointers to literal\n/// parsers.\nbytes constant SUB_PARSER_LITERAL_PARSERS = hex\"\";\n\n/// Base implementation of `ISubParserV2`. Inherit from this contract and\n/// override the virtual functions to align all the relevant pointers and\n/// metadata bytes so that it can actually run.\n/// The basic workflow for subparsing via this contract is:\n/// - The main parser will call `subParse` with the subparser's compatibility\n///   version and the data to parse.\n/// - The subparser will check the compatibility is an exact match and revert if\n///   not. This is the simplest and most conservative approach, if there's a new\n///   compatibility version, a new version of the subparser will need to be\n///   deployed even if the upstream changes are backwards compatible.\n/// - The subparser will then parse the data, using the `subParserParseMeta`\n///   function to get the metadata bytes, which must be overridden by the child\n///   contract in order to be useful. The sub parser meta bytes are constructed\n///   exactly the same as the main parser meta bytes, so the same types and libs\n///   can be used to build them. The key difference is that the index of each\n///   word in the authoring meta maps to a _parser_ function pointer, rather\n///   than a _handler_ function pointer. What this means is that the function\n///   at index N of `subParserFunctionPointers` is responsible for parsing\n///   whatever data the main parser has passed to `subParse` into whatever the\n///   final output of the subparser is. For example, the 5th parser function\n///   might convert some word string `\"foo\"` into the bytecode that represents\n///   an extern call on the main interpreter into the contract that provides\n///   that extern logic. This decoupling allows any subparser function to\n///   generate any runtime behaviour at all, provided it knows how to construct\n///   the opcode for it.\n/// - Currently the subparse handles literals and operands in the same way as\n///   the main parser, but this may change in future. Likely that there will be\n///   dedicated \"sub literal\" and \"sub word\" concepts, that should be more\n///   composable than the current approach.\n/// - The final result of the subparser is returned as a tuple of success,\n///   bytecode and constants. The success flag is used to indicate whether the\n///   subparser was able to parse the data, and the bytecode and constants are\n///   the same as the main parser, and are used to construct the final bytecode\n///   of the main parser. The expectation on failure is that there may be some\n///   other subparser that can parse the data, so the main parser will handle\n///   fallback logic.\nabstract contract BaseRainterpreterSubParserNPE2 is ERC165, ISubParserV2 {\n    using LibBytes for bytes;\n    using LibParse for ParseState;\n    using LibParseMeta for ParseState;\n    using LibParseOperand for ParseState;\n\n    /// Overrideable function to allow implementations to define their parse\n    /// meta bytes.\n    //slither-disable-next-line dead-code\n    function subParserParseMeta() internal pure virtual returns (bytes memory) {\n        return SUB_PARSER_PARSE_META;\n    }\n\n    /// Overrideable function to allow implementations to define their function\n    /// pointers to each sub parser.\n    //slither-disable-next-line dead-code\n    function subParserWordParsers() internal pure virtual returns (bytes memory) {\n        return SUB_PARSER_WORD_PARSERS;\n    }\n\n    /// Overrideable function to allow implementations to define their operand\n    /// handlers.\n    //slither-disable-next-line dead-code\n    function subParserOperandHandlers() internal pure virtual returns (bytes memory) {\n        return SUB_PARSER_OPERAND_HANDLERS;\n    }\n\n    /// Overrideable function to allow implementations to define their literal\n    /// parsers.\n    //slither-disable-next-line dead-code\n    function subParserLiteralParsers() internal pure virtual returns (bytes memory) {\n        return SUB_PARSER_LITERAL_PARSERS;\n    }\n\n    /// Overrideable function to allow implementations to define their\n    /// compatibility version. Most implementations should leave this as the\n    /// default as it matches the main parser's compatibility version as at the\n    /// same commit the abstract sub parser is pulled from.\n    //slither-disable-next-line dead-code\n    function subParserCompatibility() internal pure virtual returns (bytes32) {\n        return COMPATIBLITY_V3;\n    }\n\n    /// Overrideable function to allow implementations to define their\n    /// literal dispatch matching. This is optional, and if not overridden\n    /// simply won't attempt to parse any literals. This is usually what you\n    /// want, as the main parser will handle common literals and the subparser\n    /// can focus on words, which is the more common case.\n    /// @param cursor The cursor to the memory location of the start of the\n    /// dispatch data.\n    /// @param end The cursor to the memory location of the end of the dispatch\n    /// data.\n    /// @return success Whether the dispatch was successfully matched. If the\n    /// sub parser does not recognise the dispatch data, it should return false.\n    /// The main parser MAY fallback to other sub parsers, so this is not\n    /// necessarily a failure condition.\n    /// @return index The index of the sub parser literal parser to use. If\n    /// success is true, this MUST match the position of the function pointer in\n    /// the bytes returned by `subParserLiteralParsers`.\n    /// @return value The value of the dispatch data, which is passed to the\n    /// sub parser literal parser. This MAY be zero if the sub parser does not\n    /// need to use the dispatch data. The interpretation of this value is\n    /// entirely up to the sub parser.\n    //slither-disable-next-line dead-code\n    function matchSubParseLiteralDispatch(uint256 cursor, uint256 end)\n        internal\n        pure\n        virtual\n        returns (bool success, uint256 index, uint256 value)\n    {\n        (cursor, end);\n        success = false;\n        index = 0;\n        value = 0;\n    }\n\n    modifier onlyCompatible(bytes32 compatibility) {\n        if (compatibility != subParserCompatibility()) {\n            revert IncompatibleSubParser();\n        }\n        _;\n    }\n\n    /// A basic implementation of sub parsing literals that uses encoded\n    /// function pointers to dispatch everything necessary in O(1) and allows\n    /// for the child contract to override all relevant functions with some\n    /// modest boilerplate.\n    /// This is virtual but the expectation is that it generally DOES NOT need\n    /// to be overridden, as the function pointers and metadata bytes are all\n    /// that need to be changed to implement a new subparser.\n    /// @inheritdoc ISubParserV2\n    function subParseLiteral(bytes32 compatibility, bytes memory data)\n        external\n        pure\n        virtual\n        onlyCompatible(compatibility)\n        returns (bool, uint256)\n    {\n        (uint256 dispatchStart, uint256 bodyStart, uint256 bodyEnd) = LibSubParse.consumeSubParseLiteralInputData(data);\n\n        (bool success, uint256 index, uint256 dispatchValue) = matchSubParseLiteralDispatch(dispatchStart, bodyStart);\n\n        if (success) {\n            function (uint256, uint256, uint256) internal pure returns (uint256) subParser;\n            bytes memory localSubParserLiteralParsers = subParserLiteralParsers();\n            assembly (\"memory-safe\") {\n                subParser := and(mload(add(localSubParserLiteralParsers, mul(add(index, 1), 2))), 0xFFFF)\n            }\n            return (true, subParser(dispatchValue, bodyStart, bodyEnd));\n        } else {\n            return (false, 0);\n        }\n    }\n\n    /// A basic implementation of sub parsing words that uses encoded function\n    /// pointers to dispatch everything necessary in O(1) and allows for the\n    /// child contract to override all relevant functions with some modest\n    /// boilerplate.\n    /// This is virtual but the expectation is that it generally DOES NOT need\n    /// to be overridden, as the function pointers and metadata bytes are all\n    /// that need to be changed to implement a new subparser.\n    /// @inheritdoc ISubParserV2\n    function subParseWord(bytes32 compatibility, bytes memory data)\n        external\n        pure\n        virtual\n        onlyCompatible(compatibility)\n        returns (bool, bytes memory, uint256[] memory)\n    {\n        (uint256 constantsHeight, uint256 ioByte, ParseState memory state) =\n            LibSubParse.consumeSubParseWordInputData(data, subParserParseMeta(), subParserOperandHandlers());\n        uint256 cursor = Pointer.unwrap(state.data.dataPointer());\n        uint256 end = cursor + state.data.length;\n\n        bytes32 word;\n        (cursor, word) = LibParse.parseWord(cursor, end, CMASK_RHS_WORD_TAIL);\n        (bool exists, uint256 index) = state.lookupWord(word);\n        if (exists) {\n            Operand operand = state.handleOperand(index);\n            function (uint256, uint256, Operand) internal pure returns (bool, bytes memory, uint256[] memory) subParser;\n            bytes memory localSubParserWordParsers = subParserWordParsers();\n            assembly (\"memory-safe\") {\n                subParser := and(mload(add(localSubParserWordParsers, mul(add(index, 1), 2))), 0xFFFF)\n            }\n            return subParser(constantsHeight, ioByte, operand);\n        } else {\n            return (false, \"\", new uint256[](0));\n        }\n    }\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(ISubParserV2).interfaceId || super.supportsInterface(interfaceId);\n    }\n}\n"
      },
      "lib/rain.interpreter/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 \"../../interface/unstable/IInterpreterV2.sol\";\nimport {LibBytecode, Pointer} from \"../bytecode/LibBytecode.sol\";\nimport {ISubParserV2, COMPATIBLITY_V3} from \"../../interface/unstable/ISubParserV2.sol\";\nimport {BadSubParserResult, UnknownWord, UnsupportedLiteralType} from \"../../error/ErrParse.sol\";\nimport {LibExtern, EncodedExternDispatch} from \"../extern/LibExtern.sol\";\nimport {IInterpreterExternV3} from \"../../interface/unstable/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.interpreter/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 \"../../interface/unstable/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/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"
      },
      "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"
      },
      "lib/rain.interpreter/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/rain.intorastring/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.intorastring/lib/rain.solmem/src/lib/LibStackPointer.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport \"./LibUint256Array.sol\";\nimport \"./LibMemory.sol\";\nimport \"./LibMemCpy.sol\";\n\n/// Throws if a stack pointer is not aligned to 32 bytes.\nerror UnalignedStackPointer(Pointer pointer);\n\n/// @title LibStackPointer\n/// @notice A stack `Pointer` is still just a pointer to some memory, but we are\n/// going to treat it like it is pointing to a stack data structure. That means\n/// it can move \"up\" and \"down\" (increment and decrement) by `uint256` (32 bytes)\n/// increments. Structurally a stack is a `uint256[]` but we can save a lot of\n/// gas vs. default Solidity handling of array indexes by using assembly to\n/// bypass runtime bounds checks on every read and write. Of course, this means\n/// the caller is responsible for ensuring the stack reads and write are not out\n/// of bounds.\n///\n/// The pointer to the bottom of a stack points at the 0th item, NOT the length\n/// of the implied `uint256[]` and the top of a stack points AFTER the last item.\n/// e.g. consider a `uint256[]` in memory with values `3 A B C` and assume this\n/// starts at position `0` in memory, i.e. `0` points to value `3` for the\n/// array length. In this case the stack bottom would be `Pointer.wrap(0x20)`\n/// (32 bytes above 0, past the length) and the stack top would be\n/// `StackPointer.wrap(0x80)` (96 bytes above the stack bottom).\n///\n/// Most of the functions in this library are equivalent to each other via\n/// composition, i.e. everything could be achieved with just `up`, `down`,\n/// `pop`, `push`, `peek`. The reason there is so much overloaded/duplicated\n/// logic is that the Solidity compiler seems to fail at inlining equivalent\n/// logic quite a lot. Perhaps once the IR compilation of Solidity is better\n/// supported by tooling etc. we could remove a lot of this duplication as the\n/// compiler itself would handle the optimisations.\nlibrary LibStackPointer {\n    using LibStackPointer for Pointer;\n    using LibStackPointer for uint256[];\n    using LibStackPointer for bytes;\n    using LibUint256Array for uint256[];\n    using LibMemory for uint256;\n\n    /// Read the word immediately below the given stack pointer.\n    ///\n    /// Treats the given pointer as a pointer to the top of the stack, so `peek`\n    /// reads the word below the pointer.\n    ///\n    /// https://en.wikipedia.org/wiki/Peek_(data_type_operation)\n    ///\n    /// The caller MUST ensure this read is not out of bounds, e.g. a `peek` to\n    /// `0` will underflow (and exhaust gas attempting to read).\n    ///\n    /// @param pointer Pointer to the top of the stack to read below.\n    /// @return word The word that was read.\n    function unsafePeek(Pointer pointer) internal pure returns (uint256 word) {\n        assembly (\"memory-safe\") {\n            word := mload(sub(pointer, 0x20))\n        }\n    }\n\n    /// Peeks 2 words from the top of the stack.\n    ///\n    /// Same as `unsafePeek` but returns 2 words instead of 1.\n    ///\n    /// @param pointer The stack top to peek below.\n    /// @return lower The lower of the two words read.\n    /// @return upper The upper of the two words read.\n    function unsafePeek2(Pointer pointer) internal pure returns (uint256 lower, uint256 upper) {\n        assembly (\"memory-safe\") {\n            lower := mload(sub(pointer, 0x40))\n            upper := mload(sub(pointer, 0x20))\n        }\n    }\n\n    /// Pops the word from the top of the stack.\n    ///\n    /// Treats the given pointer as a pointer to the top of the stack, so `pop`\n    /// reads the word below the pointer. The popped pointer is returned\n    /// alongside the read word.\n    ///\n    /// https://en.wikipedia.org/wiki/Stack_(abstract_data_type)\n    ///\n    /// The caller MUST ensure the pop will not result in an out of bounds read.\n    ///\n    /// @param pointer Pointer to the top of the stack to read below.\n    /// @return pointerAfter Pointer after the pop.\n    /// @return word The word that was read.\n    function unsafePop(Pointer pointer) internal pure returns (Pointer pointerAfter, uint256 word) {\n        assembly (\"memory-safe\") {\n            pointerAfter := sub(pointer, 0x20)\n            word := mload(pointerAfter)\n        }\n    }\n\n    /// Pushes a word to the top of the stack.\n    ///\n    /// Treats the given pointer as a pointer to the top of the stack, so `push`\n    /// writes a word at the pointer. The pushed pointer is returned.\n    ///\n    /// https://en.wikipedia.org/wiki/Stack_(abstract_data_type)\n    ///\n    /// The caller MUST ensure the push will not result in an out of bounds\n    /// write.\n    ///\n    /// @param pointer The stack pointer to write at.\n    /// @param word The value to write.\n    /// @return The stack pointer above where `word` was written to.\n    function unsafePush(Pointer pointer, uint256 word) internal pure returns (Pointer) {\n        assembly (\"memory-safe\") {\n            mstore(pointer, word)\n            pointer := add(pointer, 0x20)\n        }\n        return pointer;\n    }\n\n    /// Returns `length` values from the stack as an array without allocating\n    /// new memory. As arrays always start with their length, this requires\n    /// writing the length value to the stack below the array values. The value\n    /// that is overwritten in the process is also returned so that data is not\n    /// lost. For example, imagine a stack `[ A B C D ]` and we list 2 values.\n    /// This will write the stack to look like `[ A 2 C D ]` and return both `B`\n    /// and a pointer to `2` represented as a `uint256[]`.\n    /// The returned array is ONLY valid for as long as the stack DOES NOT move\n    /// back into its memory. As soon as the stack moves up again and writes into\n    /// the array it will be corrupt. The caller MUST ensure that it does not\n    /// read from the returned array after it has been corrupted by subsequent\n    /// stack writes.\n    /// @param pointer The stack pointer to read the values below into an\n    /// array.\n    /// @param length The number of values to include in the returned array.\n    /// @return head The value that was overwritten with the length.\n    /// @return tail The array constructed from the stack memory.\n    function unsafeList(Pointer pointer, uint256 length) internal pure returns (uint256 head, uint256[] memory tail) {\n        assembly (\"memory-safe\") {\n            tail := sub(pointer, add(0x20, mul(length, 0x20)))\n            head := mload(tail)\n            mstore(tail, length)\n        }\n    }\n\n    /// Convert two stack pointer values to a single stack index. A stack index\n    /// is the distance in 32 byte increments between two stack pointers. The\n    /// calculations require the two stack pointers are aligned. If the pointers\n    /// are not aligned, the function will revert.\n    ///\n    /// @param lower The lower of the two values.\n    /// @param upper The higher of the two values.\n    /// @return The stack index as 32 byte words distance between the top and\n    /// bottom. Negative if `lower` is above `upper`.\n    function toIndexSigned(Pointer lower, Pointer upper) internal pure returns (int256) {\n        unchecked {\n            if (Pointer.unwrap(lower) % 0x20 != 0) {\n                revert UnalignedStackPointer(lower);\n            }\n            if (Pointer.unwrap(upper) % 0x20 != 0) {\n                revert UnalignedStackPointer(upper);\n            }\n            // Dividing by 0x20 before casting to a signed int avoids the case\n            // where the difference between the two pointers is greater than\n            // `type(int256).max` and would overflow the signed int.\n            return int256(Pointer.unwrap(upper) / 0x20) - int256(Pointer.unwrap(lower) / 0x20);\n        }\n    }\n}\n"
      },
      "lib/rain.intorastring/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"
      },
      "lib/rain.interpreter/src/interface/unstable/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, IInterpreterStoreV1} from \"../IInterpreterStoreV1.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        IInterpreterStoreV1 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"
      },
      "lib/rain.interpreter/src/interface/unstable/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/lib/LibUniswapV2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IUniswapV2Pair} from \"../interface/IUniswapV2Pair.sol\";\nimport {IUniswapV2Factory} from \"../interface/IUniswapV2Factory.sol\";\nimport {\n    UniswapV2ZeroAmount,\n    UniswapV2ZeroOutputAmount,\n    UniswapV2IdenticalAddresses,\n    UniswapV2ZeroAddress,\n    UniswapV2ZeroLiquidity,\n    UniswapV2ZeroInputAmount\n} from \"../error/ErrUniswapV2.sol\";\n\n/// UniswapV2Library from uniswap/v2-periphery is compiled with a version of\n/// SafeMath that is locked to Solidity 0.6.x which means we can't use it in\n/// Solidity 0.8.x. This is a copy of the library with the SafeMath dependency\n/// removed, using Solidity's built-in overflow checking.\n/// Some minor modifications have been made to the reference functions. These\n/// are noted in the comments and/or made explicit by descriptively renaming the\n/// functions to differentiate them from the original.\nlibrary LibUniswapV2 {\n    /// Copy of UniswapV2Library.sortTokens for solidity 0.8.x support.\n    function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {\n        if (tokenA == tokenB) {\n            revert UniswapV2IdenticalAddresses();\n        }\n        (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n        if (token0 == address(0)) {\n            revert UniswapV2ZeroAddress();\n        }\n    }\n\n    /// Copy of UniswapV2Library.pairFor for solidity 0.8.x support.\n    function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {\n        (address token0, address token1) = sortTokens(tokenA, tokenB);\n        pair = address(\n            uint160(\n                uint256(\n                    keccak256(\n                        abi.encodePacked(\n                            hex\"ff\",\n                            factory,\n                            keccak256(abi.encodePacked(token0, token1)),\n                            hex\"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f\" // init code hash\n                        )\n                    )\n                )\n            )\n        );\n    }\n\n    /// UniswapV2Library.sol has a `getReserves` function but it discards the\n    /// timestamp that the pair reserves were last updated at. This function\n    /// duplicates the logic of `getReserves` but returns the timestamp as well.\n    function getReservesWithTime(address factory, address tokenA, address tokenB)\n        internal\n        view\n        returns (uint256 reserveA, uint256 reserveB, uint256 timestamp)\n    {\n        (address token0,) = sortTokens(tokenA, tokenB);\n        // Reference implementation uses `pairFor` but for some reason this\n        // doesn't seem to work on sushi's factory. Using `getPair` instead.\n        // @todo investigate the discrepency.\n        address pair = IUniswapV2Factory(factory).getPair(tokenA, tokenB);\n        (uint256 reserve0, uint256 reserve1, uint256 blockTimestampLast) = IUniswapV2Pair(pair).getReserves();\n        (reserveA, reserveB, timestamp) =\n            tokenA == token0 ? (reserve0, reserve1, blockTimestampLast) : (reserve1, reserve0, blockTimestampLast);\n    }\n\n    /// Copy of UniswapV2Library.getAmountIn for solidity 0.8.x support.\n    function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut)\n        internal\n        pure\n        returns (uint256 amountIn)\n    {\n        if (amountOut == 0) {\n            revert UniswapV2ZeroOutputAmount();\n        }\n        if (reserveIn == 0 || reserveOut == 0) {\n            revert UniswapV2ZeroLiquidity();\n        }\n        uint256 numerator = reserveIn * amountOut * 1000;\n        uint256 denominator = (reserveOut - amountOut) * 997;\n        amountIn = (numerator / denominator) + 1;\n    }\n\n    /// Copy of UniswapV2Library.getAmountOut for solidity 0.8.x support.\n    function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut)\n        internal\n        pure\n        returns (uint256 amountOut)\n    {\n        if (amountIn == 0) {\n            revert UniswapV2ZeroInputAmount();\n        }\n        if (reserveIn == 0 || reserveOut == 0) {\n            revert UniswapV2ZeroLiquidity();\n        }\n\n        uint256 amountInWithFee = amountIn * 997;\n        uint256 numerator = amountInWithFee * reserveOut;\n        uint256 denominator = (reserveIn * 1000) + amountInWithFee;\n        amountOut = numerator / denominator;\n    }\n\n    /// Copy of UniswapV2Library.quote for solidity 0.8.x support.\n    function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) internal pure returns (uint256 amountB) {\n        if (amountA == 0) {\n            revert UniswapV2ZeroAmount();\n        }\n        if (reserveA == 0 || reserveB == 0) {\n            revert UniswapV2ZeroLiquidity();\n        }\n        amountB = (amountA * reserveB) / reserveA;\n    }\n\n    /// Bundles the key library logic together to produce amounts based on tokens\n    /// and amounts out rather than needing to handle reserves directly.\n    /// Also maps 0 amountOut to 0 amountIn unconditionally, which is different\n    /// to the reference implementation.\n    function getAmountInByTokenWithTime(address factory, address tokenIn, address tokenOut, uint256 amountOut)\n        internal\n        view\n        returns (uint256 amountIn, uint256 timestamp)\n    {\n        (uint256 reserveIn, uint256 reserveOut, uint256 reserveTimestamp) =\n            getReservesWithTime(factory, tokenIn, tokenOut);\n        // Perform the 0 amountOut to 0 amountIn mapping after getting the\n        // reserves so that we still error on invalid reserves.\n        amountIn = amountOut == 0 ? 0 : getAmountIn(amountOut, reserveIn, reserveOut);\n        timestamp = reserveTimestamp;\n    }\n\n    /// Bundles the key library logic together to produce amounts based on tokens\n    /// and amounts in rather than needing to handle reserves directly.\n    /// Also maps 0 amountIn to 0 amountOut unconditionally, which is different\n    /// to the reference implementation.\n    function getAmountOutByTokenWithTime(address factory, address tokenIn, address tokenOut, uint256 amountIn)\n        internal\n        view\n        returns (uint256 amountOut, uint256 timestamp)\n    {\n        (uint256 reserveIn, uint256 reserveOut, uint256 reserveTimestamp) =\n            getReservesWithTime(factory, tokenIn, tokenOut);\n        // Perform the 0 amountIn to 0 amountOut mapping after getting the\n        // reserves so that we still error on invalid reserves.\n        amountOut = amountIn == 0 ? 0 : getAmountOut(amountIn, reserveIn, reserveOut);\n        timestamp = reserveTimestamp;\n    }\n\n    /// Bundles the key library logic together to produce amounts based on tokens\n    /// and amounts out rather than needing to handle reserves directly.\n    /// Also maps 0 amountOut to 0 amountIn unconditionally, which is different\n    /// to the reference implementation.\n    function getQuoteWithTime(address factory, address tokenA, address tokenB, uint256 amountA)\n        internal\n        view\n        returns (uint256 amountB, uint256 timestamp)\n    {\n        (uint256 reserveA, uint256 reserveB, uint256 reserveTimestamp) = getReservesWithTime(factory, tokenA, tokenB);\n        // Perform the 0 amountOut to 0 amountIn mapping after getting the\n        // reserves so that we still error on invalid reserves.\n        amountB = amountA == 0 ? 0 : quote(amountA, reserveA, reserveB);\n        timestamp = reserveTimestamp;\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"
      },
      "src/lib/v3/LibUniswapV3PoolAddress.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n// From view-quoter-v3 but with 0.8.18 solidity to be rain compatible.\npragma solidity ^0.8.18;\n\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\nlibrary LibUniswapV3PoolAddress {\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\n\n    /// @notice The identifying key of the pool\n    struct PoolKey {\n        address token0;\n        address token1;\n        uint24 fee;\n    }\n\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\n    /// @param tokenA The first token of a pool, unsorted\n    /// @param tokenB The second token of a pool, unsorted\n    /// @param fee The fee level of the pool\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\n    function getPoolKey(address tokenA, address tokenB, uint24 fee) internal pure returns (PoolKey memory) {\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\n    }\n\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\n    /// @param factory The Uniswap V3 factory contract address\n    /// @param key The PoolKey\n    /// @return pool The contract address of the V3 pool\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\n        require(key.token0 < key.token1);\n        pool = address(\n            uint160(\n                uint256(\n                    keccak256(\n                        abi.encodePacked(\n                            hex\"ff\",\n                            factory,\n                            keccak256(abi.encode(key.token0, key.token1, key.fee)),\n                            POOL_INIT_CODE_HASH\n                        )\n                    )\n                )\n            )\n        );\n    }\n}\n"
      },
      "lib/v3-core/contracts/interfaces/IUniswapV3Pool.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport './pool/IUniswapV3PoolImmutables.sol';\nimport './pool/IUniswapV3PoolState.sol';\nimport './pool/IUniswapV3PoolDerivedState.sol';\nimport './pool/IUniswapV3PoolActions.sol';\nimport './pool/IUniswapV3PoolOwnerActions.sol';\nimport './pool/IUniswapV3PoolEvents.sol';\n\n/// @title The interface for a Uniswap V3 Pool\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\n/// to the ERC20 specification\n/// @dev The pool interface is broken up into many smaller pieces\ninterface IUniswapV3Pool is\n    IUniswapV3PoolImmutables,\n    IUniswapV3PoolState,\n    IUniswapV3PoolDerivedState,\n    IUniswapV3PoolActions,\n    IUniswapV3PoolOwnerActions,\n    IUniswapV3PoolEvents\n{\n\n}\n"
      },
      "src/lib/v3/LibUniswapV3TickMath.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n// TickMath from v3-core with 0.8.x support\npragma solidity >=0.5.0;\n\n/// @title Math library for computing sqrt prices from ticks and vice versa\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\n/// prices between 2**-128 and 2**128\nlibrary LibUniswapV3TickMath {\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\n    int24 internal constant MIN_TICK = -887272;\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\n    int24 internal constant MAX_TICK = -MIN_TICK;\n\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\n    /// @dev Throws if |tick| > max tick\n    /// @param tick The input tick for the above formula\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\n    /// at the given tick\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\n        // Modified to support 0.8.x with explicit typecast from int24 to uint24\n        require(absTick <= uint256(uint24(MAX_TICK)), \"T\");\n\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\n\n        if (tick > 0) ratio = type(uint256).max / ratio;\n\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\n    }\n\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\n    /// ever return.\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\n        // second inequality must be < because the price can never reach the price at the max tick\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \"R\");\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\n\n        uint256 r = ratio;\n        uint256 msb = 0;\n\n        assembly {\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(5, gt(r, 0xFFFFFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(4, gt(r, 0xFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(3, gt(r, 0xFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(2, gt(r, 0xF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(1, gt(r, 0x3))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := gt(r, 0x1)\n            msb := or(msb, f)\n        }\n\n        if (msb >= 128) r = ratio >> (msb - 127);\n        else r = ratio << (127 - msb);\n\n        int256 log_2 = (int256(msb) - 128) << 64;\n\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(63, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(62, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(61, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(60, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(59, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(58, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(57, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(56, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(55, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(54, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(53, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(52, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(51, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(50, f))\n        }\n\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\n\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\n\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\n    }\n}\n"
      },
      "lib/v3-core/contracts/libraries/FixedPoint96.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.4.0;\n\n/// @title FixedPoint96\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\n/// @dev Used in SqrtPriceMath.sol\nlibrary FixedPoint96 {\n    uint8 internal constant RESOLUTION = 96;\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\n}\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.intorastring/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.interpreter/src/interface/unstable/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"
      },
      "lib/rain.interpreter/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.interpreter/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"
      },
      "lib/rain.interpreter/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 \"../../interface/unstable/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/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 \"../../interface/unstable/IInterpreterV2.sol\";\nimport {LibParseOperand} from \"./LibParseOperand.sol\";\nimport {ParseState} from \"./LibParseState.sol\";\nimport {AuthoringMetaV2} from \"../../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"
      },
      "lib/rain.interpreter/src/lib/parse/LibParseState.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {Operand, OPCODE_CONSTANT} from \"../../interface/unstable/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"
      },
      "lib/rain.interpreter/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/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"
      },
      "lib/rain.interpreter/src/lib/extern/LibExtern.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {IInterpreterV2, Operand} from \"../../interface/unstable/IInterpreterV2.sol\";\nimport {\n    IInterpreterExternV3,\n    ExternDispatch,\n    EncodedExternDispatch\n} from \"../../interface/unstable/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.intorastring/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"
      },
      "lib/rain.interpreter/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"
      },
      "lib/rain.interpreter/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"
      },
      "lib/rain.interpreter/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"
      },
      "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.intorastring/lib/rain.solmem/src/lib/LibMemory.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nlibrary LibMemory {\n    /// Returns true if the free memory pointer is pointing at a multiple of 32\n    /// bytes, false otherwise. If all memory allocations are handled by Solidity\n    /// then this will always be true, but assembly blocks can violate this, so\n    /// this is a useful tool to test compliance of a custom assembly block with\n    /// the solidity allocator.\n    /// @return isAligned true if the memory is currently aligned to 32 bytes.\n    function memoryIsAligned() internal pure returns (bool isAligned) {\n        assembly (\"memory-safe\") {\n            isAligned := iszero(mod(mload(0x40), 0x20))\n        }\n    }\n}\n"
      },
      "lib/rain.intorastring/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"
      },
      "lib/rain.interpreter/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/src/interface/IInterpreterStoreV1.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\nimport {StateNamespace} from \"./deprecated/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/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"
      },
      "src/interface/IUniswapV2Pair.sol": {
        "content": "pragma solidity ^0.8.18;\n\ninterface IUniswapV2Pair {\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    function name() external pure returns (string memory);\n    function symbol() external pure returns (string memory);\n    function decimals() external pure returns (uint8);\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address owner) external view returns (uint256);\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    function approve(address spender, uint256 value) external returns (bool);\n    function transfer(address to, uint256 value) external returns (bool);\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n\n    // Can't modify this as it comes from uniswap.\n    //slither-disable-next-line naming-convention\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n    // Can't modify this as it comes from uniswap.\n    //slither-disable-next-line naming-convention\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\n    function nonces(address owner) external view returns (uint256);\n\n    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n        external;\n\n    event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n    event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);\n    event Swap(\n        address indexed sender,\n        uint256 amount0In,\n        uint256 amount1In,\n        uint256 amount0Out,\n        uint256 amount1Out,\n        address indexed to\n    );\n    event Sync(uint112 reserve0, uint112 reserve1);\n\n    // Can't modify this as it comes from uniswap.\n    //slither-disable-next-line naming-convention\n    function MINIMUM_LIQUIDITY() external pure returns (uint256);\n    function factory() external view returns (address);\n    function token0() external view returns (address);\n    function token1() external view returns (address);\n    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n    function price0CumulativeLast() external view returns (uint256);\n    function price1CumulativeLast() external view returns (uint256);\n    function kLast() external view returns (uint256);\n\n    function mint(address to) external returns (uint256 liquidity);\n    function burn(address to) external returns (uint256 amount0, uint256 amount1);\n    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;\n    function skim(address to) external;\n    function sync() external;\n\n    function initialize(address, address) external;\n}\n"
      },
      "src/interface/IUniswapV2Factory.sol": {
        "content": "pragma solidity ^0.8.18;\n\ninterface IUniswapV2Factory {\n    event PairCreated(address indexed token0, address indexed token1, address pair, uint256);\n\n    function feeTo() external view returns (address);\n    function feeToSetter() external view returns (address);\n\n    function getPair(address tokenA, address tokenB) external view returns (address pair);\n    function allPairs(uint256) external view returns (address pair);\n    function allPairsLength() external view returns (uint256);\n\n    function createPair(address tokenA, address tokenB) external returns (address pair);\n\n    function setFeeTo(address) external;\n    function setFeeToSetter(address) external;\n}\n"
      },
      "src/error/ErrUniswapV2.sol": {
        "content": "// SPDX-License-Identifier: CAL\npragma solidity ^0.8.18;\n\n/// @dev Thrown when an undirected amount is zero.\nerror UniswapV2ZeroAmount();\n\n/// @dev Thrown when an input amount is zero.\nerror UniswapV2ZeroInputAmount();\n\n/// @dev Throw when an output amount is zero.\nerror UniswapV2ZeroOutputAmount();\n\n/// @dev Thrown when a reserve is zero.\nerror UniswapV2ZeroLiquidity();\n\n/// @dev Thrown when the two token addresses are identical.\nerror UniswapV2IdenticalAddresses();\n\n/// @dev Thrown when some token address is the zero address.\nerror UniswapV2ZeroAddress();\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/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3PoolImmutables {\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\n    /// @return The contract address\n    function factory() external view returns (address);\n\n    /// @notice The first of the two tokens of the pool, sorted by address\n    /// @return The token contract address\n    function token0() external view returns (address);\n\n    /// @notice The second of the two tokens of the pool, sorted by address\n    /// @return The token contract address\n    function token1() external view returns (address);\n\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n    /// @return The fee\n    function fee() external view returns (uint24);\n\n    /// @notice The pool tick spacing\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\n    /// This value is an int24 to avoid casting even though it is always positive.\n    /// @return The tick spacing\n    function tickSpacing() external view returns (int24);\n\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\n    /// @return The max amount of liquidity per tick\n    function maxLiquidityPerTick() external view returns (uint128);\n}\n"
      },
      "lib/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that can change\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\n/// per transaction\ninterface IUniswapV3PoolState {\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\n    /// when accessed externally.\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\n    /// boundary.\n    /// observationIndex The index of the last oracle observation that was written,\n    /// observationCardinality The current maximum number of observations stored in the pool,\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n    /// feeProtocol The protocol fee for both tokens of the pool.\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\n    /// unlocked Whether the pool is currently locked to reentrancy\n    function slot0()\n        external\n        view\n        returns (\n            uint160 sqrtPriceX96,\n            int24 tick,\n            uint16 observationIndex,\n            uint16 observationCardinality,\n            uint16 observationCardinalityNext,\n            uint8 feeProtocol,\n            bool unlocked\n        );\n\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\n    /// @dev This value can overflow the uint256\n    function feeGrowthGlobal0X128() external view returns (uint256);\n\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\n    /// @dev This value can overflow the uint256\n    function feeGrowthGlobal1X128() external view returns (uint256);\n\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\n    /// @dev Protocol fees will never exceed uint128 max in either token\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\n\n    /// @notice The currently in range liquidity available to the pool\n    /// @dev This value has no relationship to the total liquidity across all ticks\n    function liquidity() external view returns (uint128);\n\n    /// @notice Look up information about a specific tick in the pool\n    /// @param tick The tick to look up\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\n    /// tick upper,\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\n    /// a specific position.\n    function ticks(int24 tick)\n        external\n        view\n        returns (\n            uint128 liquidityGross,\n            int128 liquidityNet,\n            uint256 feeGrowthOutside0X128,\n            uint256 feeGrowthOutside1X128,\n            int56 tickCumulativeOutside,\n            uint160 secondsPerLiquidityOutsideX128,\n            uint32 secondsOutside,\n            bool initialized\n        );\n\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\n\n    /// @notice Returns the information about a position by the position's key\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\n    /// @return _liquidity The amount of liquidity in the position,\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\n    function positions(bytes32 key)\n        external\n        view\n        returns (\n            uint128 _liquidity,\n            uint256 feeGrowthInside0LastX128,\n            uint256 feeGrowthInside1LastX128,\n            uint128 tokensOwed0,\n            uint128 tokensOwed1\n        );\n\n    /// @notice Returns data about a specific observation index\n    /// @param index The element of the observations array to fetch\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\n    /// ago, rather than at a specific index in the array.\n    /// @return blockTimestamp The timestamp of the observation,\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\n    function observations(uint256 index)\n        external\n        view\n        returns (\n            uint32 blockTimestamp,\n            int56 tickCumulative,\n            uint160 secondsPerLiquidityCumulativeX128,\n            bool initialized\n        );\n}\n"
      },
      "lib/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that is not stored\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\n/// blockchain. The functions here may have variable gas costs.\ninterface IUniswapV3PoolDerivedState {\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\n    /// you must call it with secondsAgos = [3600, 0].\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\n    /// timestamp\n    function observe(uint32[] calldata secondsAgos)\n        external\n        view\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\n\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\n    /// snapshot is taken and the second snapshot is taken.\n    /// @param tickLower The lower tick of the range\n    /// @param tickUpper The upper tick of the range\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\n        external\n        view\n        returns (\n            int56 tickCumulativeInside,\n            uint160 secondsPerLiquidityInsideX128,\n            uint32 secondsInside\n        );\n}\n"
      },
      "lib/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissionless pool actions\n/// @notice Contains pool methods that can be called by anyone\ninterface IUniswapV3PoolActions {\n    /// @notice Sets the initial price for the pool\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\n    function initialize(uint160 sqrtPriceX96) external;\n\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\n    /// @param recipient The address for which the liquidity will be created\n    /// @param tickLower The lower tick of the position in which to add liquidity\n    /// @param tickUpper The upper tick of the position in which to add liquidity\n    /// @param amount The amount of liquidity to mint\n    /// @param data Any data that should be passed through to the callback\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\n    function mint(\n        address recipient,\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount,\n        bytes calldata data\n    ) external returns (uint256 amount0, uint256 amount1);\n\n    /// @notice Collects tokens owed to a position\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\n    /// @param recipient The address which should receive the fees collected\n    /// @param tickLower The lower tick of the position for which to collect fees\n    /// @param tickUpper The upper tick of the position for which to collect fees\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\n    /// @return amount0 The amount of fees collected in token0\n    /// @return amount1 The amount of fees collected in token1\n    function collect(\n        address recipient,\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount0Requested,\n        uint128 amount1Requested\n    ) external returns (uint128 amount0, uint128 amount1);\n\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\n    /// @dev Fees must be collected separately via a call to #collect\n    /// @param tickLower The lower tick of the position for which to burn liquidity\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\n    /// @param amount How much liquidity to burn\n    /// @return amount0 The amount of token0 sent to the recipient\n    /// @return amount1 The amount of token1 sent to the recipient\n    function burn(\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount\n    ) external returns (uint256 amount0, uint256 amount1);\n\n    /// @notice Swap token0 for token1, or token1 for token0\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\n    /// @param recipient The address to receive the output of the swap\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\n    /// @param data Any data to be passed through to the callback\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\n    function swap(\n        address recipient,\n        bool zeroForOne,\n        int256 amountSpecified,\n        uint160 sqrtPriceLimitX96,\n        bytes calldata data\n    ) external returns (int256 amount0, int256 amount1);\n\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\n    /// @param recipient The address which will receive the token0 and token1 amounts\n    /// @param amount0 The amount of token0 to send\n    /// @param amount1 The amount of token1 to send\n    /// @param data Any data to be passed through to the callback\n    function flash(\n        address recipient,\n        uint256 amount0,\n        uint256 amount1,\n        bytes calldata data\n    ) external;\n\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\n    /// the input observationCardinalityNext.\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\n}\n"
      },
      "lib/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissioned pool actions\n/// @notice Contains pool methods that may only be called by the factory owner\ninterface IUniswapV3PoolOwnerActions {\n    /// @notice Set the denominator of the protocol's % share of the fees\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n\n    /// @notice Collect the protocol fee accrued to the pool\n    /// @param recipient The address to which collected protocol fees should be sent\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\n    /// @return amount0 The protocol fee collected in token0\n    /// @return amount1 The protocol fee collected in token1\n    function collectProtocol(\n        address recipient,\n        uint128 amount0Requested,\n        uint128 amount1Requested\n    ) external returns (uint128 amount0, uint128 amount1);\n}\n"
      },
      "lib/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Events emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolEvents {\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\n\n    /// @notice Emitted when liquidity is minted for a given position\n    /// @param sender The address that minted the liquidity\n    /// @param owner The owner of the position and recipient of any minted liquidity\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount The amount of liquidity minted to the position range\n    /// @param amount0 How much token0 was required for the minted liquidity\n    /// @param amount1 How much token1 was required for the minted liquidity\n    event Mint(\n        address sender,\n        address indexed owner,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount,\n        uint256 amount0,\n        uint256 amount1\n    );\n\n    /// @notice Emitted when fees are collected by the owner of a position\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\n    /// @param owner The owner of the position for which fees are collected\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount0 The amount of token0 fees collected\n    /// @param amount1 The amount of token1 fees collected\n    event Collect(\n        address indexed owner,\n        address recipient,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount0,\n        uint128 amount1\n    );\n\n    /// @notice Emitted when a position's liquidity is removed\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\n    /// @param owner The owner of the position for which liquidity is removed\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount The amount of liquidity to remove\n    /// @param amount0 The amount of token0 withdrawn\n    /// @param amount1 The amount of token1 withdrawn\n    event Burn(\n        address indexed owner,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount,\n        uint256 amount0,\n        uint256 amount1\n    );\n\n    /// @notice Emitted by the pool for any swaps between token0 and token1\n    /// @param sender The address that initiated the swap call, and that received the callback\n    /// @param recipient The address that received the output of the swap\n    /// @param amount0 The delta of the token0 balance of the pool\n    /// @param amount1 The delta of the token1 balance of the pool\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n    /// @param liquidity The liquidity of the pool after the swap\n    /// @param tick The log base 1.0001 of price of the pool after the swap\n    event Swap(\n        address indexed sender,\n        address indexed recipient,\n        int256 amount0,\n        int256 amount1,\n        uint160 sqrtPriceX96,\n        uint128 liquidity,\n        int24 tick\n    );\n\n    /// @notice Emitted by the pool for any flashes of token0/token1\n    /// @param sender The address that initiated the swap call, and that received the callback\n    /// @param recipient The address that received the tokens from flash\n    /// @param amount0 The amount of token0 that was flashed\n    /// @param amount1 The amount of token1 that was flashed\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\n    event Flash(\n        address indexed sender,\n        address indexed recipient,\n        uint256 amount0,\n        uint256 amount1,\n        uint256 paid0,\n        uint256 paid1\n    );\n\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\n    /// just before a mint/swap/burn.\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\n    event IncreaseObservationCardinalityNext(\n        uint16 observationCardinalityNextOld,\n        uint16 observationCardinalityNextNew\n    );\n\n    /// @notice Emitted when the protocol fee is changed by the pool\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\n\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\n    /// @param sender The address that collects the protocol fees\n    /// @param recipient The address that receives the collected protocol fees\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\n}\n"
      },
      "lib/rain.interpreter/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"
      },
      "lib/rain.interpreter/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"
      },
      "lib/rain.interpreter/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"
      },
      "lib/rain.interpreter/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"
      },
      "lib/rain.interpreter/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/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"
      }
    },
    "settings": {
      "remappings": [
        "rain.interpreter/=lib/rain.interpreter/src/",
        "@openzeppelin/=lib/view-quoter-v3/lib/openzeppelin-contracts/",
        "@prb/test/=lib/rain.interpreter/lib/prb-math/lib/prb-test/src/",
        "@uniswap/v3-core/=lib/view-quoter-v3/lib/v3-core/",
        "bitwise/=lib/rain.interpreter/src/lib/bitwise/",
        "bytecode/=lib/rain.interpreter/src/lib/bytecode/",
        "caller/=lib/rain.interpreter/src/lib/caller/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "eval/=lib/rain.interpreter/src/lib/eval/",
        "extern/=lib/rain.interpreter/src/lib/extern/",
        "forge-std/=lib/forge-std/src/",
        "integrity/=lib/rain.interpreter/src/lib/integrity/",
        "ns/=lib/rain.interpreter/src/lib/ns/",
        "op/=lib/rain.interpreter/src/lib/op/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "parse/=lib/rain.interpreter/src/lib/parse/",
        "prb-math/=lib/rain.interpreter/lib/prb-math/src/",
        "prb-test/=lib/rain.interpreter/lib/prb-math/lib/prb-test/src/",
        "rain.chainlink/=lib/rain.interpreter/lib/rain.chainlink/src/",
        "rain.datacontract/=lib/rain.interpreter/lib/rain.datacontract/src/",
        "rain.erc1820/=lib/rain.interpreter/lib/rain.erc1820/src/",
        "rain.intorastring/=lib/rain.intorastring/",
        "rain.lib.hash/=lib/rain.interpreter/lib/rain.lib.memkv/lib/rain.lib.hash/src/",
        "rain.lib.memkv/=lib/rain.interpreter/lib/rain.lib.memkv/src/",
        "rain.lib.typecast/=lib/rain.interpreter/lib/rain.lib.typecast/src/",
        "rain.math.fixedpoint/=lib/rain.math.fixedpoint/src/",
        "rain.math.saturating/=lib/rain.interpreter/lib/rain.math.saturating/src/",
        "rain.metadata/=lib/rain.interpreter/lib/rain.metadata/",
        "rain.solmem/=lib/rain.intorastring/lib/rain.solmem/src/",
        "rain.will-overflow/=lib/rain.will-overflow/",
        "sol.lib.binmaskflag/=lib/rain.interpreter/lib/sol.lib.binmaskflag/src/",
        "solmate/=lib/view-quoter-v3/lib/solmate/",
        "state/=lib/rain.interpreter/src/lib/state/",
        "v3-core/=lib/v3-core/",
        "v3-periphery/=lib/view-quoter-v3/lib/v3-periphery/",
        "view-quoter-v3/=lib/view-quoter-v3/"
      ],
      "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": {}
    }
  }}