creation_sourcecode: {{
    "language": "Solidity",
    "settings": {
      "evmVersion": "paris",
      "libraries": {},
      "metadata": {
        "bytecodeHash": "ipfs",
        "useLiteralContent": true
      },
      "optimizer": {
        "enabled": true,
        "runs": 4000
      },
      "remappings": [],
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    },
    "sources": {
      "contracts/verifiers/UniswapSwapVerifier.sol": {
        "content": "// Verification Key Hash: 90921f2636bd13faadabc1e4b490b37d456243318e0566d2b81119fa56315c92\n// SPDX-License-Identifier: Apache-2.0\n// Copyright 2022 Aztec\npragma solidity >=0.8.4;\n\nlibrary UltraVerificationKey {\n    function verificationKeyHash() internal pure returns(bytes32) {\n        return 0x90921f2636bd13faadabc1e4b490b37d456243318e0566d2b81119fa56315c92;\n    }\n\n    function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure {\n        assembly {\n            mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000010000) // vk.circuit_size\n            mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000009) // vk.num_inputs\n            mstore(add(_vk, 0x40), 0x00eeb2cb5981ed45649abebde081dcff16c8601de4347e7dd1628ba2daac43b7) // vk.work_root\n            mstore(add(_vk, 0x60), 0x30641e0e92bebef818268d663bcad6dbcfd6c0149170f6d7d350b1b1fa6c1001) // vk.domain_inverse\n            mstore(add(_vk, 0x80), 0x1f139ed493b29006f7f06c9152510043c232a04ea87f805ce125249af3475c39) // vk.Q1.x\n            mstore(add(_vk, 0xa0), 0x192b5f60ba8892d8015a5166c5be44cc9a72e59133ec0f2a16d6e1d3f3debcf5) // vk.Q1.y\n            mstore(add(_vk, 0xc0), 0x2bdb39116d7c2da005d875beccad7714f2a6d312186684febaa57a58a9764b02) // vk.Q2.x\n            mstore(add(_vk, 0xe0), 0x1070574c15d181d174811dde0636e8cab220f929b0c7ad71dc0405abad540361) // vk.Q2.y\n            mstore(add(_vk, 0x100), 0x16865962a25eccb38adde06b89163d6e752e1810d643dba5b232169e79ecafef) // vk.Q3.x\n            mstore(add(_vk, 0x120), 0x2b9807340b768624647187f0e6f51c8a95a5af14d783502ec3fd92334f5f1139) // vk.Q3.y\n            mstore(add(_vk, 0x140), 0x10c63ceeada18fa07466e650155e22da0a05023b5959a9d2832212e54fb7d8c5) // vk.Q4.x\n            mstore(add(_vk, 0x160), 0x002f627cbcbb3287790db6669053f3cdce05fe9f3238d664f202a8d691f76345) // vk.Q4.y\n            mstore(add(_vk, 0x180), 0x2c85d8aab2436e502e58ead6eba9dea6dcffc85a52cf8f248a58d2744785a199) // vk.Q_M.x\n            mstore(add(_vk, 0x1a0), 0x037091c567fe5207e153e1530fae1f5bedca759edcf5fb16baefb6768ae40c78) // vk.Q_M.y\n            mstore(add(_vk, 0x1c0), 0x0d5d112ca21e85e0bc918ca85d80c7fc98f01255b26c39a864fb181eb2305ab1) // vk.Q_C.x\n            mstore(add(_vk, 0x1e0), 0x0ee5f9582bc6c2e1f4c690544e28a5ea97967bf5fc626b7b0a2499490fe01a60) // vk.Q_C.y\n            mstore(add(_vk, 0x200), 0x21db6460da4a58c1657f6eef7f54d1ede81e9e5b197543f36e5d1e67789b9ce2) // vk.Q_ARITHMETIC.x\n            mstore(add(_vk, 0x220), 0x1d11d6e7d46f8647dd25d0fb420e6dd7ae1b7d1da40edc6b625dc60fc092a4de) // vk.Q_ARITHMETIC.y\n            mstore(add(_vk, 0x240), 0x20689b450530775f16df8cce76a7f81017922e733c0f8d240a4a3e0d0fde8e01) // vk.QSORT.x\n            mstore(add(_vk, 0x260), 0x03e8689d9986ba4d6837e0f854b9d54f8d404151affeb3058c2d921fc8f7fc39) // vk.QSORT.y\n            mstore(add(_vk, 0x280), 0x27b49176a777308f17add59f6306fa05c8edb5ab66dd1f5fa1a9c2c623a16b4a) // vk.Q_ELLIPTIC.x\n            mstore(add(_vk, 0x2a0), 0x1db2db9a811753a5847532448580869bec32e97f8bdae27dba954924855bf46f) // vk.Q_ELLIPTIC.y\n            mstore(add(_vk, 0x2c0), 0x2a89b8102ccfc49933d74e02fe48d47687520ae0389774ac1baabf538e986861) // vk.Q_AUX.x\n            mstore(add(_vk, 0x2e0), 0x10f4817a46d99d626fa8dc8fbd386b560956c3f40c1605d804c599586f2c7490) // vk.Q_AUX.y\n            mstore(add(_vk, 0x300), 0x07145a9408d2145497b73cf4928d6d578c0f12fb6e2bb193aca950b66a3fdba7) // vk.SIGMA1.x\n            mstore(add(_vk, 0x320), 0x22a59de42be7ea1f476cb889c1060f6ffca0218711718192b14ec4eff8590042) // vk.SIGMA1.y\n            mstore(add(_vk, 0x340), 0x29c80c31bc55b67df6a8cd4c1b20b0bc8968e12e4ceb816b71a7f4308839f0fd) // vk.SIGMA2.x\n            mstore(add(_vk, 0x360), 0x28d3516dcabba4e82104a74e3ad73989a7076c573537e891bb8592b5f71e52d9) // vk.SIGMA2.y\n            mstore(add(_vk, 0x380), 0x2fe7a56021c6491263f279cd7a1153da843e111a97fbd4e048c227461d7424be) // vk.SIGMA3.x\n            mstore(add(_vk, 0x3a0), 0x27d2a155665e0a0bef73bf2bdb650ec679436b1c528e812093a099fb79d1f6d2) // vk.SIGMA3.y\n            mstore(add(_vk, 0x3c0), 0x2477fb913236f6971c28878a21a9557489c1a2c5e6cd19ff314fea11d796f8fb) // vk.SIGMA4.x\n            mstore(add(_vk, 0x3e0), 0x1b2e259063057b70a43fcff57c72c472ddc676587b8599baf0ba9b50171b6306) // vk.SIGMA4.y\n            mstore(add(_vk, 0x400), 0x138c2f5e3fd1228e915c151690b2eb796bc33156f2923d689525f0c497014bce) // vk.TABLE1.x\n            mstore(add(_vk, 0x420), 0x0be85de8976f8fec0ad349778e206b8aaddf792b14a5dccd435e97bbc93bcace) // vk.TABLE1.y\n            mstore(add(_vk, 0x440), 0x0ed87af976c50be820eb4f5ea0c527ce51e72f1a5dfb05356650ec788be9b3b1) // vk.TABLE2.x\n            mstore(add(_vk, 0x460), 0x08af0b20f80fe572de2f990dd6176b3ffed42494d8a331095eff8a2943c63bb3) // vk.TABLE2.y\n            mstore(add(_vk, 0x480), 0x2832fbb1b93ead5801aa4b196942a14323ce60c38aa5ed53547574f09038d2f9) // vk.TABLE3.x\n            mstore(add(_vk, 0x4a0), 0x01403b05d9723bcfbf5bed8f44ac099f986d4417e0a3b1a0d8d76959ed976952) // vk.TABLE3.y\n            mstore(add(_vk, 0x4c0), 0x16cc5ccf3d71031db63b44d57bdc8f8b622d5ff4a41ab2a36f4c9e486b4e1328) // vk.TABLE4.x\n            mstore(add(_vk, 0x4e0), 0x1b812a62c41e800ff958c93d6f602840309b850409e207a5d34368ddc6eb8d65) // vk.TABLE4.y\n            mstore(add(_vk, 0x500), 0x00fe0ceb2002656769a1afc05207687e2b7ad06ea86da4c29788120ee75a794c) // vk.TABLE_TYPE.x\n            mstore(add(_vk, 0x520), 0x17d239b1479f25cac0333833bece3dfffa88ff15ddc423e6c201e394515ccde8) // vk.TABLE_TYPE.y\n            mstore(add(_vk, 0x540), 0x16d0b1228b660d71d13ce0e1aaf7e8df16fb464426850b1b011659bd4335c75c) // vk.ID1.x\n            mstore(add(_vk, 0x560), 0x26ed294a6a416d0b2b2518d324abc117b4567c89902931e6965155daa0bf56bb) // vk.ID1.y\n            mstore(add(_vk, 0x580), 0x00ac2af8b9baaccdbeef00933f841d3292a8b79eeb16c9dbd6f99d34ea835307) // vk.ID2.x\n            mstore(add(_vk, 0x5a0), 0x08ec9a8554e250682bbce0d9e189fb09aac9d674af2d94403027703c8b5f56f9) // vk.ID2.y\n            mstore(add(_vk, 0x5c0), 0x239bc9d1941a2611062ad4e9d5aee30aa1261461c7915e5a052443224aac190c) // vk.ID3.x\n            mstore(add(_vk, 0x5e0), 0x2207f8769e6107fe82befb97a0d8c48f7d320cf1489b0826cfbcfdf0d263815d) // vk.ID3.y\n            mstore(add(_vk, 0x600), 0x120bed096b7e8127b79788d1876aac2f3386e288e1260c9c81e23049fa40d976) // vk.ID4.x\n            mstore(add(_vk, 0x620), 0x07b4939cb5551978f3812b224309281739de26abbc74bc6fac550a6316421f9d) // vk.ID4.y\n            mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof\n            mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices\n            mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 \n            mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 \n            mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 \n            mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 \n            mstore(_omegaInverseLoc, 0x0b5d56b77fe704e8e92338c0082f37e091126414c830e4c6922d5ac802d842d4) // vk.work_root_inverse\n        }\n    }\n}\n\n/**\n * @title Ultra Plonk proof verification contract\n * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified\n */\nabstract contract BaseUltraVerifier {\n    // VERIFICATION KEY MEMORY LOCATIONS\n    uint256 internal constant N_LOC = 0x380;\n    uint256 internal constant NUM_INPUTS_LOC = 0x3a0;\n    uint256 internal constant OMEGA_LOC = 0x3c0;\n    uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0;\n    uint256 internal constant Q1_X_LOC = 0x400;\n    uint256 internal constant Q1_Y_LOC = 0x420;\n    uint256 internal constant Q2_X_LOC = 0x440;\n    uint256 internal constant Q2_Y_LOC = 0x460;\n    uint256 internal constant Q3_X_LOC = 0x480;\n    uint256 internal constant Q3_Y_LOC = 0x4a0;\n    uint256 internal constant Q4_X_LOC = 0x4c0;\n    uint256 internal constant Q4_Y_LOC = 0x4e0;\n    uint256 internal constant QM_X_LOC = 0x500;\n    uint256 internal constant QM_Y_LOC = 0x520;\n    uint256 internal constant QC_X_LOC = 0x540;\n    uint256 internal constant QC_Y_LOC = 0x560;\n    uint256 internal constant QARITH_X_LOC = 0x580;\n    uint256 internal constant QARITH_Y_LOC = 0x5a0;\n    uint256 internal constant QSORT_X_LOC = 0x5c0;\n    uint256 internal constant QSORT_Y_LOC = 0x5e0;\n    uint256 internal constant QELLIPTIC_X_LOC = 0x600;\n    uint256 internal constant QELLIPTIC_Y_LOC = 0x620;\n    uint256 internal constant QAUX_X_LOC = 0x640;\n    uint256 internal constant QAUX_Y_LOC = 0x660;\n    uint256 internal constant SIGMA1_X_LOC = 0x680;\n    uint256 internal constant SIGMA1_Y_LOC = 0x6a0;\n    uint256 internal constant SIGMA2_X_LOC = 0x6c0;\n    uint256 internal constant SIGMA2_Y_LOC = 0x6e0;\n    uint256 internal constant SIGMA3_X_LOC = 0x700;\n    uint256 internal constant SIGMA3_Y_LOC = 0x720;\n    uint256 internal constant SIGMA4_X_LOC = 0x740;\n    uint256 internal constant SIGMA4_Y_LOC = 0x760;\n    uint256 internal constant TABLE1_X_LOC = 0x780;\n    uint256 internal constant TABLE1_Y_LOC = 0x7a0;\n    uint256 internal constant TABLE2_X_LOC = 0x7c0;\n    uint256 internal constant TABLE2_Y_LOC = 0x7e0;\n    uint256 internal constant TABLE3_X_LOC = 0x800;\n    uint256 internal constant TABLE3_Y_LOC = 0x820;\n    uint256 internal constant TABLE4_X_LOC = 0x840;\n    uint256 internal constant TABLE4_Y_LOC = 0x860;\n    uint256 internal constant TABLE_TYPE_X_LOC = 0x880;\n    uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0;\n    uint256 internal constant ID1_X_LOC = 0x8c0;\n    uint256 internal constant ID1_Y_LOC = 0x8e0;\n    uint256 internal constant ID2_X_LOC = 0x900;\n    uint256 internal constant ID2_Y_LOC = 0x920;\n    uint256 internal constant ID3_X_LOC = 0x940;\n    uint256 internal constant ID3_Y_LOC = 0x960;\n    uint256 internal constant ID4_X_LOC = 0x980;\n    uint256 internal constant ID4_Y_LOC = 0x9a0;\n    uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0;\n    uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0;\n    uint256 internal constant G2X_X0_LOC = 0xa00;\n    uint256 internal constant G2X_X1_LOC = 0xa20;\n    uint256 internal constant G2X_Y0_LOC = 0xa40;\n    uint256 internal constant G2X_Y1_LOC = 0xa60;\n\n    // ### PROOF DATA MEMORY LOCATIONS\n    uint256 internal constant W1_X_LOC = 0x1200;\n    uint256 internal constant W1_Y_LOC = 0x1220;\n    uint256 internal constant W2_X_LOC = 0x1240;\n    uint256 internal constant W2_Y_LOC = 0x1260;\n    uint256 internal constant W3_X_LOC = 0x1280;\n    uint256 internal constant W3_Y_LOC = 0x12a0;\n    uint256 internal constant W4_X_LOC = 0x12c0;\n    uint256 internal constant W4_Y_LOC = 0x12e0;\n    uint256 internal constant S_X_LOC = 0x1300;\n    uint256 internal constant S_Y_LOC = 0x1320;\n    uint256 internal constant Z_X_LOC = 0x1340;\n    uint256 internal constant Z_Y_LOC = 0x1360;\n    uint256 internal constant Z_LOOKUP_X_LOC = 0x1380;\n    uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0;\n    uint256 internal constant T1_X_LOC = 0x13c0;\n    uint256 internal constant T1_Y_LOC = 0x13e0;\n    uint256 internal constant T2_X_LOC = 0x1400;\n    uint256 internal constant T2_Y_LOC = 0x1420;\n    uint256 internal constant T3_X_LOC = 0x1440;\n    uint256 internal constant T3_Y_LOC = 0x1460;\n    uint256 internal constant T4_X_LOC = 0x1480;\n    uint256 internal constant T4_Y_LOC = 0x14a0;\n\n    uint256 internal constant W1_EVAL_LOC = 0x1600;\n    uint256 internal constant W2_EVAL_LOC = 0x1620;\n    uint256 internal constant W3_EVAL_LOC = 0x1640;\n    uint256 internal constant W4_EVAL_LOC = 0x1660;\n    uint256 internal constant S_EVAL_LOC = 0x1680;\n    uint256 internal constant Z_EVAL_LOC = 0x16a0;\n    uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0;\n    uint256 internal constant Q1_EVAL_LOC = 0x16e0;\n    uint256 internal constant Q2_EVAL_LOC = 0x1700;\n    uint256 internal constant Q3_EVAL_LOC = 0x1720;\n    uint256 internal constant Q4_EVAL_LOC = 0x1740;\n    uint256 internal constant QM_EVAL_LOC = 0x1760;\n    uint256 internal constant QC_EVAL_LOC = 0x1780;\n    uint256 internal constant QARITH_EVAL_LOC = 0x17a0;\n    uint256 internal constant QSORT_EVAL_LOC = 0x17c0;\n    uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0;\n    uint256 internal constant QAUX_EVAL_LOC = 0x1800;\n    uint256 internal constant TABLE1_EVAL_LOC = 0x1840;\n    uint256 internal constant TABLE2_EVAL_LOC = 0x1860;\n    uint256 internal constant TABLE3_EVAL_LOC = 0x1880;\n    uint256 internal constant TABLE4_EVAL_LOC = 0x18a0;\n    uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0;\n    uint256 internal constant ID1_EVAL_LOC = 0x18e0;\n    uint256 internal constant ID2_EVAL_LOC = 0x1900;\n    uint256 internal constant ID3_EVAL_LOC = 0x1920;\n    uint256 internal constant ID4_EVAL_LOC = 0x1940;\n    uint256 internal constant SIGMA1_EVAL_LOC = 0x1960;\n    uint256 internal constant SIGMA2_EVAL_LOC = 0x1980;\n    uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0;\n    uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0;\n    uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0;\n    uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000;\n    uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020;\n    uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040;\n    uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060;\n    uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080;\n    uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0;\n    uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0;\n    uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0;\n    uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100;\n    uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120;\n\n    uint256 internal constant PI_Z_X_LOC = 0x2300;\n    uint256 internal constant PI_Z_Y_LOC = 0x2320;\n    uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340;\n    uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360;\n\n    // Used for elliptic widget. These are alias names for wire + shifted wire evaluations\n    uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC;\n    uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC;\n    uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC;\n    uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC;\n    uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC;\n    uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC;\n    uint256 internal constant QBETA_LOC = Q3_EVAL_LOC;\n    uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC;\n    uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC;\n\n    // ### CHALLENGES MEMORY OFFSETS\n\n    uint256 internal constant C_BETA_LOC = 0x2600;\n    uint256 internal constant C_GAMMA_LOC = 0x2620;\n    uint256 internal constant C_ALPHA_LOC = 0x2640;\n    uint256 internal constant C_ETA_LOC = 0x2660;\n    uint256 internal constant C_ETA_SQR_LOC = 0x2680;\n    uint256 internal constant C_ETA_CUBE_LOC = 0x26a0;\n\n    uint256 internal constant C_ZETA_LOC = 0x26c0;\n    uint256 internal constant C_CURRENT_LOC = 0x26e0;\n    uint256 internal constant C_V0_LOC = 0x2700;\n    uint256 internal constant C_V1_LOC = 0x2720;\n    uint256 internal constant C_V2_LOC = 0x2740;\n    uint256 internal constant C_V3_LOC = 0x2760;\n    uint256 internal constant C_V4_LOC = 0x2780;\n    uint256 internal constant C_V5_LOC = 0x27a0;\n    uint256 internal constant C_V6_LOC = 0x27c0;\n    uint256 internal constant C_V7_LOC = 0x27e0;\n    uint256 internal constant C_V8_LOC = 0x2800;\n    uint256 internal constant C_V9_LOC = 0x2820;\n    uint256 internal constant C_V10_LOC = 0x2840;\n    uint256 internal constant C_V11_LOC = 0x2860;\n    uint256 internal constant C_V12_LOC = 0x2880;\n    uint256 internal constant C_V13_LOC = 0x28a0;\n    uint256 internal constant C_V14_LOC = 0x28c0;\n    uint256 internal constant C_V15_LOC = 0x28e0;\n    uint256 internal constant C_V16_LOC = 0x2900;\n    uint256 internal constant C_V17_LOC = 0x2920;\n    uint256 internal constant C_V18_LOC = 0x2940;\n    uint256 internal constant C_V19_LOC = 0x2960;\n    uint256 internal constant C_V20_LOC = 0x2980;\n    uint256 internal constant C_V21_LOC = 0x29a0;\n    uint256 internal constant C_V22_LOC = 0x29c0;\n    uint256 internal constant C_V23_LOC = 0x29e0;\n    uint256 internal constant C_V24_LOC = 0x2a00;\n    uint256 internal constant C_V25_LOC = 0x2a20;\n    uint256 internal constant C_V26_LOC = 0x2a40;\n    uint256 internal constant C_V27_LOC = 0x2a60;\n    uint256 internal constant C_V28_LOC = 0x2a80;\n    uint256 internal constant C_V29_LOC = 0x2aa0;\n    uint256 internal constant C_V30_LOC = 0x2ac0;\n\n    uint256 internal constant C_U_LOC = 0x2b00;\n\n    // ### LOCAL VARIABLES MEMORY OFFSETS\n    uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000;\n    uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020;\n    uint256 internal constant ZETA_POW_N_LOC = 0x3040;\n    uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060;\n    uint256 internal constant ZERO_POLY_LOC = 0x3080;\n    uint256 internal constant L_START_LOC = 0x30a0;\n    uint256 internal constant L_END_LOC = 0x30c0;\n    uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0;\n\n    uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100;\n    uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120;\n    uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140;\n\n    uint256 internal constant ACCUMULATOR_X_LOC = 0x3160;\n    uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180;\n    uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0;\n    uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0;\n    uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0;\n    uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200;\n    uint256 internal constant PAIRING_RHS_X_LOC = 0x3220;\n    uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240;\n\n    // misc stuff\n    uint256 internal constant OMEGA_INVERSE_LOC = 0x3300;\n    uint256 internal constant C_ALPHA_SQR_LOC = 0x3320;\n    uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340;\n    uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360;\n    uint256 internal constant C_ALPHA_BASE_LOC = 0x3380;\n\n    // ### RECURSION VARIABLE MEMORY LOCATIONS\n    uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400;\n    uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420;\n    uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440;\n    uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460;\n    uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480;\n\n    // sub-identity storage\n    uint256 internal constant PERMUTATION_IDENTITY = 0x3500;\n    uint256 internal constant PLOOKUP_IDENTITY = 0x3520;\n    uint256 internal constant ARITHMETIC_IDENTITY = 0x3540;\n    uint256 internal constant SORT_IDENTITY = 0x3560;\n    uint256 internal constant ELLIPTIC_IDENTITY = 0x3580;\n    uint256 internal constant AUX_IDENTITY = 0x35a0;\n    uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0;\n    uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0;\n    uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600;\n    uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620;\n    uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640;\n\n    uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660;\n    uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680;\n\n    // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time\n    uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0;\n    uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0;\n    uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0;\n\n    bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf;\n    bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654;\n    bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6;\n    bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f;\n    bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc;\n    bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81;\n    bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763;\n    bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263;\n\n    uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes\n\n    // We need to hash 41 field elements when generating the NU challenge\n    // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14)\n    // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7)\n    // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9)\n    // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7)\n    // table1_omega, table2_omega, table3_omega, table4_omega (4)\n    uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20\n\n    // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over\n    // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4\n    uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0\n\n    uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P =\n        0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;\n    uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68\n    uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14\n\n    // y^2 = x^3 + ax + b\n    // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic\n    uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17;\n\n    error INVALID_VERIFICATION_KEY();\n    error POINT_NOT_ON_CURVE();\n    error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual);\n    error PUBLIC_INPUT_INVALID_BN128_G1_POINT();\n    error PUBLIC_INPUT_GE_P();\n    error MOD_EXP_FAILURE();\n    error PAIRING_PREAMBLE_FAILED();\n    error OPENING_COMMITMENT_FAILED();\n    error PAIRING_FAILED();\n\n    function getVerificationKeyHash() public pure virtual returns (bytes32);\n\n    /**\n     * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment\n     */\n    function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual;\n\n    constructor() { \n        loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC);\n\n        // We verify that all of the EC points in the verification key lie on the bn128 curve. \n        assembly {\n            let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order\n\n            let success := 1\n\n            // VALIDATE Q1\n            {\n                let x := mload(Q1_X_LOC)\n                let y := mload(Q1_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE Q2\n            {\n                let x := mload(Q2_X_LOC)\n                let y := mload(Q2_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE Q3\n            {\n                let x := mload(Q3_X_LOC)\n                let y := mload(Q3_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE Q4\n            {\n                let x := mload(Q4_X_LOC)\n                let y := mload(Q4_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            // VALIDATE QM\n            {\n                let x := mload(QM_X_LOC)\n                let y := mload(QM_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE QC\n            {\n                let x := mload(QC_X_LOC)\n                let y := mload(QC_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE QARITH\n            {\n                let x := mload(QARITH_X_LOC)\n                let y := mload(QARITH_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE QSORT\n            {\n                let x := mload(QSORT_X_LOC)\n                let y := mload(QSORT_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE QELLIPTIC\n            {\n                let x := mload(QELLIPTIC_X_LOC)\n                let y := mload(QELLIPTIC_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE QAUX\n            {\n                let x := mload(QAUX_X_LOC)\n                let y := mload(QAUX_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE SIGMA1\n            {\n                let x := mload(SIGMA1_X_LOC)\n                let y := mload(SIGMA1_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE SIGMA2\n            {\n                let x := mload(SIGMA2_X_LOC)\n                let y := mload(SIGMA2_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE SIGMA3\n            {\n                let x := mload(SIGMA3_X_LOC)\n                let y := mload(SIGMA3_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE SIGMA4\n            {\n                let x := mload(SIGMA4_X_LOC)\n                let y := mload(SIGMA4_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE TABLE1\n            {\n                let x := mload(TABLE1_X_LOC)\n                let y := mload(TABLE1_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            } \n            // VALIDATE TABLE2\n            {\n                let x := mload(TABLE2_X_LOC)\n                let y := mload(TABLE2_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            } \n            // VALIDATE TABLE3\n            {\n                let x := mload(TABLE3_X_LOC)\n                let y := mload(TABLE3_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            } \n            // VALIDATE TABLE4\n            {\n                let x := mload(TABLE4_X_LOC)\n                let y := mload(TABLE4_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            } \n            // VALIDATE TABLE_TYPE\n            {\n                let x := mload(TABLE_TYPE_X_LOC)\n                let y := mload(TABLE_TYPE_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE ID1\n            {\n                let x := mload(ID1_X_LOC)\n                let y := mload(ID1_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE ID2\n            {\n                let x := mload(ID2_X_LOC)\n                let y := mload(ID2_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE ID3\n            {\n                let x := mload(ID3_X_LOC)\n                let y := mload(ID3_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n            // VALIDATE ID4\n            {\n                let x := mload(ID4_X_LOC)\n                let y := mload(ID4_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))\n            }\n\n            if iszero(success) {\n                mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR)\n                revert(0x00, 0x04)\n            }\n        }\n    }\n\n    /**\n     * @notice Verify a Ultra Plonk proof\n     * @param _proof - The serialized proof\n     * @param _publicInputs - An array of the public inputs\n     * @return True if proof is valid, reverts otherwise\n     */\n    function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) {\n        loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC);\n\n        uint256 requiredPublicInputCount;\n        assembly {\n            requiredPublicInputCount := mload(NUM_INPUTS_LOC)\n        }\n        if (requiredPublicInputCount != _publicInputs.length) {\n            revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length);\n        }\n\n        assembly {\n            let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order\n            let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order\n\n            /**\n             * LOAD PROOF FROM CALLDATA\n             */\n            {\n                let data_ptr := add(calldataload(0x04), 0x24)\n\n                mstore(W1_Y_LOC, mod(calldataload(data_ptr), q))\n                mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q))\n\n                mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q))\n                mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q))\n\n                mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q))\n                mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q))\n\n                mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q))\n                mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q))\n\n                mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q))\n                mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q))\n                mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q))\n                mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q))\n                mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q))\n                mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q))\n                mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q))\n                mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q))\n\n                mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q))\n                mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q))\n\n                mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q))\n                mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q))\n\n                mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q))\n                mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q))\n\n                mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p))\n                mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p))\n                mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p))\n                mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p))\n                mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p))\n                mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p))\n                mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p))\n                mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p))\n                mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p))\n                mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p))\n                mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p))\n                mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p))\n                mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p))\n                mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p))\n                mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p))\n                mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p))\n                mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p))\n\n                mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p))\n                mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p))\n\n                mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p))\n                mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p))\n\n                mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p))\n                mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p))\n                mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p))\n                mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p))\n                mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p))\n\n                mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p))\n                mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p))\n                mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p))\n                mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p))\n\n                mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p))\n                mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p))\n                mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p))\n                mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p))\n                mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p))\n\n                mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p))\n\n                mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p))\n                mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p))\n                mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p))\n                mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p))\n                mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p))\n\n                mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q))\n                mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q))\n\n                mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q))\n                mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q))\n            }\n\n            /**\n             * LOAD RECURSIVE PROOF INTO MEMORY\n             */\n            {\n                if mload(CONTAINS_RECURSIVE_PROOF_LOC) {\n                    let public_inputs_ptr := add(calldataload(0x24), 0x24)\n                    let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr)\n\n                    let x0 := calldataload(index_counter)\n                    x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20))))\n                    x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40))))\n                    x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60))))\n                    let y0 := calldataload(add(index_counter, 0x80))\n                    y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0))))\n                    y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0))))\n                    y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0))))\n                    let x1 := calldataload(add(index_counter, 0x100))\n                    x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120))))\n                    x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140))))\n                    x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160))))\n                    let y1 := calldataload(add(index_counter, 0x180))\n                    y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0))))\n                    y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0))))\n                    y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0))))\n                    mstore(RECURSIVE_P1_X_LOC, x0)\n                    mstore(RECURSIVE_P1_Y_LOC, y0)\n                    mstore(RECURSIVE_P2_X_LOC, x1)\n                    mstore(RECURSIVE_P2_Y_LOC, y1)\n\n                    // validate these are valid bn128 G1 points\n                    if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) {\n                        mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR)\n                        revert(0x00, 0x04)\n                    }\n                }\n            }\n\n            {\n                /**\n                 * Generate initial challenge\n                 */\n                mstore(0x00, shl(224, mload(N_LOC)))\n                mstore(0x04, shl(224, mload(NUM_INPUTS_LOC)))\n                let challenge := keccak256(0x00, 0x08)\n\n                /**\n                 * Generate eta challenge\n                 */\n                mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge)\n                // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs\n                let public_inputs_start := add(calldataload(0x24), 0x24)\n                // copy the public inputs over\n                let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20)\n                calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size)\n\n                // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length)\n                let w_start := add(calldataload(0x04), 0x24)\n                calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH)\n\n                // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0)\n                let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH))\n\n                challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size)\n                {\n                    let eta := mod(challenge, p)\n                    mstore(C_ETA_LOC, eta)\n                    mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p))\n                    mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p))\n                }\n\n                /**\n                 * Generate beta challenge\n                 */\n                mstore(0x00, challenge)\n                mstore(0x20, mload(W4_Y_LOC))\n                mstore(0x40, mload(W4_X_LOC))\n                mstore(0x60, mload(S_Y_LOC))\n                mstore(0x80, mload(S_X_LOC))\n                challenge := keccak256(0x00, 0xa0)\n                mstore(C_BETA_LOC, mod(challenge, p))\n\n                /**\n                 * Generate gamma challenge\n                 */\n                mstore(0x00, challenge)\n                mstore8(0x20, 0x01)\n                challenge := keccak256(0x00, 0x21)\n                mstore(C_GAMMA_LOC, mod(challenge, p))\n\n                /**\n                 * Generate alpha challenge\n                 */\n                mstore(0x00, challenge)\n                mstore(0x20, mload(Z_Y_LOC))\n                mstore(0x40, mload(Z_X_LOC))\n                mstore(0x60, mload(Z_LOOKUP_Y_LOC))\n                mstore(0x80, mload(Z_LOOKUP_X_LOC))\n                challenge := keccak256(0x00, 0xa0)\n                mstore(C_ALPHA_LOC, mod(challenge, p))\n\n                /**\n                 * Compute and store some powers of alpha for future computations\n                 */\n                let alpha := mload(C_ALPHA_LOC)\n                mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p))\n                mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p))\n                mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p))\n                mstore(C_ALPHA_BASE_LOC, alpha)\n\n                /**\n                 * Generate zeta challenge\n                 */\n                mstore(0x00, challenge)\n                mstore(0x20, mload(T1_Y_LOC))\n                mstore(0x40, mload(T1_X_LOC))\n                mstore(0x60, mload(T2_Y_LOC))\n                mstore(0x80, mload(T2_X_LOC))\n                mstore(0xa0, mload(T3_Y_LOC))\n                mstore(0xc0, mload(T3_X_LOC))\n                mstore(0xe0, mload(T4_Y_LOC))\n                mstore(0x100, mload(T4_X_LOC))\n\n                challenge := keccak256(0x00, 0x120)\n\n                mstore(C_ZETA_LOC, mod(challenge, p))\n                mstore(C_CURRENT_LOC, challenge)\n            }\n\n            /**\n             * EVALUATE FIELD OPERATIONS\n             */\n\n            /**\n             * COMPUTE PUBLIC INPUT DELTA\n             * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ)\n             */\n            {\n                let beta := mload(C_BETA_LOC) // β\n                let gamma := mload(C_GAMMA_LOC) // γ\n                let work_root := mload(OMEGA_LOC) // ω\n                let numerator_value := 1\n                let denominator_value := 1\n\n                let p_clone := p // move p to the front of the stack\n                let valid_inputs := true\n\n                // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24])\n                let public_inputs_ptr := add(calldataload(0x24), 0x24)\n\n                // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes\n                let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20))\n\n                // root_1 = β * 0x05\n                let root_1 := mulmod(beta, 0x05, p_clone) // k1.β\n                // root_2 = β * 0x0c\n                let root_2 := mulmod(beta, 0x0c, p_clone)\n                // @note 0x05 + 0x07 == 0x0c == external coset generator\n\n                for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } {\n                    /**\n                     * input = public_input[i]\n                     * valid_inputs &= input < p\n                     * temp = input + gamma\n                     * numerator_value *= (β.σ(i) + wᵢ + γ)  // σ(i) = 0x05.ωⁱ\n                     * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ\n                     * root_1 *= ω\n                     * root_2 *= ω\n                     */\n\n                    let input := calldataload(public_inputs_ptr)\n                    valid_inputs := and(valid_inputs, lt(input, p_clone))\n                    let temp := addmod(input, gamma, p_clone)\n\n                    numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone)\n                    denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone)\n\n                    root_1 := mulmod(root_1, work_root, p_clone)\n                    root_2 := mulmod(root_2, work_root, p_clone)\n                }\n\n                // Revert if not all public inputs are field elements (i.e. < p)\n                if iszero(valid_inputs) {\n                    mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n\n                mstore(DELTA_NUMERATOR_LOC, numerator_value)\n                mstore(DELTA_DENOMINATOR_LOC, denominator_value)\n            }\n\n            /**\n             * Compute Plookup delta factor [γ(1 + β)]^{n-k}\n             * k = num roots cut out of Z_H = 4\n             */\n            {\n                let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)\n                let delta_numerator := delta_base\n                {\n                    let exponent := mload(N_LOC)\n                    let count := 1\n                    for {} lt(count, exponent) { count := add(count, count) } {\n                        delta_numerator := mulmod(delta_numerator, delta_numerator, p)\n                    }\n                }\n                mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator)\n\n                let delta_denominator := mulmod(delta_base, delta_base, p)\n                delta_denominator := mulmod(delta_denominator, delta_denominator, p)\n                mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator)\n            }\n            /**\n             * Compute lagrange poly and vanishing poly fractions\n             */\n            {\n                /**\n                 * vanishing_numerator = zeta\n                 * ZETA_POW_N = zeta^n\n                 * vanishing_numerator -= 1\n                 * accumulating_root = omega_inverse\n                 * work_root = p - accumulating_root\n                 * domain_inverse = domain_inverse\n                 * vanishing_denominator = zeta + work_root\n                 * work_root *= accumulating_root\n                 * vanishing_denominator *= (zeta + work_root)\n                 * work_root *= accumulating_root\n                 * vanishing_denominator *= (zeta + work_root)\n                 * vanishing_denominator *= (zeta + (zeta + accumulating_root))\n                 * work_root = omega\n                 * lagrange_numerator = vanishing_numerator * domain_inverse\n                 * l_start_denominator = zeta - 1\n                 * accumulating_root = work_root^2\n                 * l_end_denominator = accumulating_root^2 * work_root * zeta - 1\n                 * Note: l_end_denominator term contains a term \\omega^5 to cut out 5 roots of unity from vanishing poly\n                 */\n\n                let zeta := mload(C_ZETA_LOC)\n\n                // compute zeta^n, where n is a power of 2\n                let vanishing_numerator := zeta\n                {\n                    // pow_small\n                    let exponent := mload(N_LOC)\n                    let count := 1\n                    for {} lt(count, exponent) { count := add(count, count) } {\n                        vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p)\n                    }\n                }\n                mstore(ZETA_POW_N_LOC, vanishing_numerator)\n                vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p)\n\n                let accumulating_root := mload(OMEGA_INVERSE_LOC)\n                let work_root := sub(p, accumulating_root)\n                let domain_inverse := mload(DOMAIN_INVERSE_LOC)\n\n                let vanishing_denominator := addmod(zeta, work_root, p)\n                work_root := mulmod(work_root, accumulating_root, p)\n                vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)\n                work_root := mulmod(work_root, accumulating_root, p)\n                vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)\n                vanishing_denominator :=\n                    mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p)\n\n                work_root := mload(OMEGA_LOC)\n\n                let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p)\n                let l_start_denominator := addmod(zeta, sub(p, 1), p)\n\n                accumulating_root := mulmod(work_root, work_root, p)\n\n                let l_end_denominator :=\n                    addmod(\n                        mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p\n                    )\n\n                /**\n                 * Compute inversions using Montgomery's batch inversion trick\n                 */\n                let accumulator := mload(DELTA_DENOMINATOR_LOC)\n                let t0 := accumulator\n                accumulator := mulmod(accumulator, vanishing_denominator, p)\n                let t1 := accumulator\n                accumulator := mulmod(accumulator, vanishing_numerator, p)\n                let t2 := accumulator\n                accumulator := mulmod(accumulator, l_start_denominator, p)\n                let t3 := accumulator\n                accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)\n                let t4 := accumulator\n                {\n                    mstore(0, 0x20)\n                    mstore(0x20, 0x20)\n                    mstore(0x40, 0x20)\n                    mstore(0x60, mulmod(accumulator, l_end_denominator, p))\n                    mstore(0x80, sub(p, 2))\n                    mstore(0xa0, p)\n                    if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) {\n                        mstore(0x0, MOD_EXP_FAILURE_SELECTOR)\n                        revert(0x00, 0x04)\n                    }\n                    accumulator := mload(0x00)\n                }\n\n                t4 := mulmod(accumulator, t4, p)\n                accumulator := mulmod(accumulator, l_end_denominator, p)\n\n                t3 := mulmod(accumulator, t3, p)\n                accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)\n\n                t2 := mulmod(accumulator, t2, p)\n                accumulator := mulmod(accumulator, l_start_denominator, p)\n\n                t1 := mulmod(accumulator, t1, p)\n                accumulator := mulmod(accumulator, vanishing_numerator, p)\n\n                t0 := mulmod(accumulator, t0, p)\n                accumulator := mulmod(accumulator, vanishing_denominator, p)\n\n                accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p)\n\n                mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p))\n                mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p))\n                mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p))\n                mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p))\n                mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p))\n                mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p))\n            }\n\n            /**\n             * UltraPlonk Widget Ordering:\n             *\n             * 1. Permutation widget\n             * 2. Plookup widget\n             * 3. Arithmetic widget\n             * 4. Fixed base widget (?)\n             * 5. GenPermSort widget\n             * 6. Elliptic widget\n             * 7. Auxiliary widget\n             */\n\n            /**\n             * COMPUTE PERMUTATION WIDGET EVALUATION\n             */\n            {\n                let alpha := mload(C_ALPHA_LOC)\n                let beta := mload(C_BETA_LOC)\n                let gamma := mload(C_GAMMA_LOC)\n\n                /**\n                 * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2)\n                 * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4)\n                 * result = alpha_base * z_eval * t1 * t2\n                 * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval)\n                 * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval)\n                 * result -= (alpha_base * z_omega_eval * t1 * t2)\n                 */\n                let t1 :=\n                    mulmod(\n                        add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)),\n                        add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)),\n                        p\n                    )\n                let t2 :=\n                    mulmod(\n                        add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)),\n                        add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)),\n                        p\n                    )\n                let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p)\n                t1 :=\n                    mulmod(\n                        add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)),\n                        add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)),\n                        p\n                    )\n                t2 :=\n                    mulmod(\n                        add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)),\n                        add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)),\n                        p\n                    )\n                result :=\n                    addmod(\n                        result,\n                        sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)),\n                        p\n                    )\n\n                /**\n                 * alpha_base *= alpha\n                 * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI}))\n                 * alpha_base *= alpha\n                 * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1))\n                 * alpha_Base *= alpha\n                 */\n                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))\n                result :=\n                    addmod(\n                        result,\n                        mulmod(\n                            mload(C_ALPHA_BASE_LOC),\n                            mulmod(\n                                mload(L_END_LOC),\n                                addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p),\n                                p\n                            ),\n                            p\n                        ),\n                        p\n                    )\n                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))\n                mstore(\n                    PERMUTATION_IDENTITY,\n                    addmod(\n                        result,\n                        mulmod(\n                            mload(C_ALPHA_BASE_LOC),\n                            mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p),\n                            p\n                        ),\n                        p\n                    )\n                )\n                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))\n            }\n\n            /**\n             * COMPUTE PLOOKUP WIDGET EVALUATION\n             */\n            {\n                /**\n                 * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³\n                 * f = η.q3(z)\n                 * f += (w3(z) + qc.w_3(zω))\n                 * f *= η\n                 * f += (w2(z) + qm.w2(zω))\n                 * f *= η\n                 * f += (w1(z) + q2.w1(zω))\n                 */\n                let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p)\n                f :=\n                    addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p)\n                f := mulmod(f, mload(C_ETA_LOC), p)\n                f :=\n                    addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p)\n                f := mulmod(f, mload(C_ETA_LOC), p)\n                f :=\n                    addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p)\n\n                // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z)\n                let t :=\n                    addmod(\n                        addmod(\n                            addmod(\n                                mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),\n                                mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p),\n                                p\n                            ),\n                            mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p),\n                            p\n                        ),\n                        mload(TABLE1_EVAL_LOC),\n                        p\n                    )\n\n                // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw)\n                let t_omega :=\n                    addmod(\n                        addmod(\n                            addmod(\n                                mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),\n                                mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p),\n                                p\n                            ),\n                            mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p),\n                            p\n                        ),\n                        mload(TABLE1_OMEGA_EVAL_LOC),\n                        p\n                    )\n\n                /**\n                 * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1)\n                 * gamma_beta_constant = γ(β + 1)\n                 * numerator = f * TABLE_TYPE_EVAL + gamma\n                 * temp0 = t(z) + t(zω) * β + gamma_beta_constant\n                 * numerator *= temp0\n                 * numerator *= (β + 1)\n                 * temp0 = alpha * l_1\n                 * numerator += temp0\n                 * numerator *= z_lookup(z)\n                 * numerator -= temp0\n                 */\n                let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)\n                let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p)\n                let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p)\n                numerator := mulmod(numerator, temp0, p)\n                numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p)\n                temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p)\n                numerator := addmod(numerator, temp0, p)\n                numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p)\n                numerator := addmod(numerator, sub(p, temp0), p)\n\n                /**\n                 * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z)\n                 * note: delta_factor = [γ(1 + β)]^{n-k}\n                 * denominator = s(z) + βs(zω) + γ(β + 1)\n                 * temp1 = α²L_end(z)\n                 * denominator -= temp1\n                 * denominator *= z_lookup(zω)\n                 * denominator += temp1 * delta_factor\n                 * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base\n                 * alpha_base *= alpha^3\n                 */\n                let denominator :=\n                    addmod(\n                        addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p),\n                        gamma_beta_constant,\n                        p\n                    )\n                let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p)\n                denominator := addmod(denominator, sub(p, temp1), p)\n                denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p)\n                denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p)\n\n                mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p))\n\n                // update alpha\n                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))\n            }\n\n            /**\n             * COMPUTE ARITHMETIC WIDGET EVALUATION\n             */\n            {\n                /**\n                 * The basic arithmetic gate identity in standard plonk is as follows.\n                 * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0\n                 * However, for Ultraplonk, we extend this to support \"passing\" wires between rows (shown without alpha scaling below):\n                 * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) +\n                 * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0\n                 *\n                 * This formula results in several cases depending on q_arith:\n                 * 1. q_arith == 0: Arithmetic gate is completely disabled\n                 *\n                 * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation\n                 * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0\n                 *\n                 * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is:\n                 * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0\n                 * It allows defining w_4 at next index (w_4_omega) in terms of current wire values\n                 *\n                 * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split\n                 * the equation into two:\n                 *\n                 * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0\n                 * and\n                 * w_1 + w_4 - w_1_omega + q_m = 0  (we are reusing q_m here)\n                 *\n                 * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1).\n                 * The equation can be split into two:\n                 *\n                 * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0\n                 * and\n                 * w_1 + w_4 - w_1_omega + q_m = 0\n                 *\n                 * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at\n                 * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at\n                 * product.\n                 */\n\n                let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p)\n                let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p)\n                let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p)\n                let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p)\n\n                // @todo - Add a explicit test that hits QARITH == 3\n                // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2\n                let w1w2qm :=\n                    mulmod(\n                        mulmod(\n                            mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p),\n                            addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p),\n                            p\n                        ),\n                        NEGATIVE_INVERSE_OF_2_MODULO_P,\n                        p\n                    )\n\n                // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c\n                let identity :=\n                    addmod(\n                        mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p\n                    )\n\n                // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where:\n                // w_1 + w_4 - w_1_omega + q_m = 0\n                // we use this gate to save an addition gate when adding or subtracting non-native field elements\n                // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m)\n                let extra_small_addition_gate_identity :=\n                    mulmod(\n                        mload(C_ALPHA_LOC),\n                        mulmod(\n                            addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p),\n                            addmod(\n                                mload(QM_EVAL_LOC),\n                                addmod(\n                                    sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p\n                                ),\n                                p\n                            ),\n                            p\n                        ),\n                        p\n                    )\n\n                // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity\n                // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires!\n                // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity))\n                mstore(\n                    ARITHMETIC_IDENTITY,\n                    mulmod(\n                        mload(C_ALPHA_BASE_LOC),\n                        mulmod(\n                            mload(QARITH_EVAL_LOC),\n                            addmod(\n                                identity,\n                                mulmod(\n                                    addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p),\n                                    addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p),\n                                    p\n                                ),\n                                p\n                            ),\n                            p\n                        ),\n                        p\n                    )\n                )\n\n                // update alpha\n                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p))\n            }\n\n            /**\n             * COMPUTE GENPERMSORT WIDGET EVALUATION\n             */\n            {\n                /**\n                 * D1 = (w2 - w1)\n                 * D2 = (w3 - w2)\n                 * D3 = (w4 - w3)\n                 * D4 = (w1_omega - w4)\n                 *\n                 * α_a = alpha_base\n                 * α_b = alpha_base * α\n                 * α_c = alpha_base * α^2\n                 * α_d = alpha_base * α^3\n                 *\n                 * range_accumulator = (\n                 *   D1(D1 - 1)(D1 - 2)(D1 - 3).α_a +\n                 *   D2(D2 - 1)(D2 - 2)(D2 - 3).α_b +\n                 *   D3(D3 - 1)(D3 - 2)(D3 - 3).α_c +\n                 *   D4(D4 - 1)(D4 - 2)(D4 - 3).α_d +\n                 * ) . q_sort\n                 */\n                let minus_two := sub(p, 2)\n                let minus_three := sub(p, 3)\n                let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)\n                let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)\n                let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)\n                let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)\n\n                let range_accumulator :=\n                    mulmod(\n                        mulmod(\n                            mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p),\n                            addmod(d1, minus_three, p),\n                            p\n                        ),\n                        mload(C_ALPHA_BASE_LOC),\n                        p\n                    )\n                range_accumulator :=\n                    addmod(\n                        range_accumulator,\n                        mulmod(\n                            mulmod(\n                                mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p),\n                                addmod(d2, minus_three, p),\n                                p\n                            ),\n                            mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                range_accumulator :=\n                    addmod(\n                        range_accumulator,\n                        mulmod(\n                            mulmod(\n                                mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p),\n                                addmod(d3, minus_three, p),\n                                p\n                            ),\n                            mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                range_accumulator :=\n                    addmod(\n                        range_accumulator,\n                        mulmod(\n                            mulmod(\n                                mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p),\n                                addmod(d4, minus_three, p),\n                                p\n                            ),\n                            mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p)\n\n                mstore(SORT_IDENTITY, range_accumulator)\n\n                // update alpha\n                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))\n            }\n\n            /**\n             * COMPUTE ELLIPTIC WIDGET EVALUATION\n             */\n            {\n                /**\n                 * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta\n                 * endo_sqr_term = x_2^2\n                 * endo_sqr_term *= (x_3 - x_1)\n                 * endo_sqr_term *= q_beta^2\n                 * leftovers = x_2^2\n                 * leftovers *= x_2\n                 * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget\n                 * leftovers -= (y_2^2 + y_1^2)\n                 * sign_term = y_2 * y_1\n                 * sign_term += sign_term\n                 * sign_term *= q_sign\n                 */\n                // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0\n                let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p)\n                let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p)\n                let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p)\n                let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p)\n\n                let x_add_identity :=\n                    addmod(\n                        mulmod(\n                            addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p),\n                            mulmod(x_diff, x_diff, p),\n                            p\n                        ),\n                        addmod(\n                            sub(\n                                p,\n                                addmod(y2_sqr, y1_sqr, p)\n                            ),\n                            addmod(y1y2, y1y2, p),\n                            p\n                        ),\n                        p\n                    )\n                x_add_identity :=\n                    mulmod(\n                        mulmod(\n                            x_add_identity,\n                            addmod(\n                                1,\n                                sub(p, mload(QM_EVAL_LOC)),\n                                p\n                            ),\n                            p\n                        ),\n                        mload(C_ALPHA_BASE_LOC),\n                        p\n                    )\n\n                // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0\n                let y1_plus_y3 := addmod(\n                    mload(Y1_EVAL_LOC),\n                    mload(Y3_EVAL_LOC),\n                    p\n                )\n                let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p)\n                let y_add_identity :=\n                    addmod(\n                        mulmod(y1_plus_y3, x_diff, p),\n                        mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p),\n                        p\n                    )\n                y_add_identity :=\n                    mulmod(\n                        mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p),\n                        mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),\n                        p\n                    )\n\n                // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL\n                mstore(\n                    ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p)\n                )\n            }\n            {\n                /**\n                 * x_pow_4 = (y_1_sqr - curve_b) * x_1;\n                 * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr;\n                 * y_1_sqr_mul_4 += y_1_sqr_mul_4;\n                 * x_1_pow_4_mul_9 = x_pow_4;\n                 * x_1_pow_4_mul_9 += x_1_pow_4_mul_9;\n                 * x_1_pow_4_mul_9 += x_1_pow_4_mul_9;\n                 * x_1_pow_4_mul_9 += x_1_pow_4_mul_9;\n                 * x_1_pow_4_mul_9 += x_pow_4;\n                 * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr;\n                 * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9;\n                 * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3);\n                 */\n                // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0\n                let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p)\n                let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p)\n                let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p)\n                let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p)\n                let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p)\n                let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p)\n                let x_double_identity :=\n                    addmod(\n                        mulmod(\n                            addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p),\n                            y1_sqr_mul_4,\n                            p\n                        ),\n                        sub(p, x1_pow_4_mul_9),\n                        p\n                    )\n                // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0\n                let y_double_identity :=\n                    addmod(\n                        mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p),\n                        sub(\n                            p,\n                            mulmod(\n                                addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p),\n                                addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p),\n                                p\n                            )\n                        ),\n                        p\n                    )\n                x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p)\n                y_double_identity :=\n                    mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p)\n                x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p)\n                y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p)\n                // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL\n                mstore(\n                    ELLIPTIC_IDENTITY,\n                    addmod(\n                        mload(ELLIPTIC_IDENTITY),\n                        mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p),\n                        p\n                    )\n                )\n\n                // update alpha\n                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))\n            }\n\n            /**\n             * COMPUTE AUXILIARY WIDGET EVALUATION\n             */\n            {\n                {\n                    /**\n                     * Non native field arithmetic gate 2\n                     *             _                                                                               _\n                     *            /   _                   _                               _       14                \\\n                     * q_2 . q_4 |   (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2    - w_3 - w_4   |\n                     *            \\_                                                                               _/\n                     *\n                     * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2\n                     * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega\n                     * non_native_field_gate_2 = non_native_field_gate_2 * limb_size\n                     * non_native_field_gate_2 -= w_4_omega\n                     * non_native_field_gate_2 += limb_subproduct\n                     * non_native_field_gate_2 *= q_4\n                     * limb_subproduct *= limb_size\n                     * limb_subproduct += w_1_omega * w_2_omega\n                     * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3\n                     * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m\n                     * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2\n                     */\n\n                    let limb_subproduct :=\n                        addmod(\n                            mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p),\n                            mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p),\n                            p\n                        )\n\n                    let non_native_field_gate_2 :=\n                        addmod(\n                            addmod(\n                                mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p),\n                                mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p),\n                                p\n                            ),\n                            sub(p, mload(W3_OMEGA_EVAL_LOC)),\n                            p\n                        )\n                    non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p)\n                    non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)\n                    non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p)\n                    non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p)\n                    limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p)\n                    limb_subproduct :=\n                        addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p)\n                    let non_native_field_gate_1 :=\n                        mulmod(\n                            addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p),\n                            mload(Q3_EVAL_LOC),\n                            p\n                        )\n                    let non_native_field_gate_3 :=\n                        mulmod(\n                            addmod(\n                                addmod(limb_subproduct, mload(W4_EVAL_LOC), p),\n                                sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)),\n                                p\n                            ),\n                            mload(QM_EVAL_LOC),\n                            p\n                        )\n                    let non_native_field_identity :=\n                        mulmod(\n                            addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p),\n                            mload(Q2_EVAL_LOC),\n                            p\n                        )\n\n                    mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity)\n                }\n\n                {\n                    /**\n                     * limb_accumulator_1 = w_2_omega;\n                     * limb_accumulator_1 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_1 += w_1_omega;\n                     * limb_accumulator_1 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_1 += w_3;\n                     * limb_accumulator_1 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_1 += w_2;\n                     * limb_accumulator_1 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_1 += w_1;\n                     * limb_accumulator_1 -= w_4;\n                     * limb_accumulator_1 *= q_4;\n                     */\n                    let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)\n                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p)\n                    limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)\n                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p)\n                    limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)\n                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p)\n                    limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)\n                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p)\n                    limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p)\n                    limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p)\n\n                    /**\n                     * limb_accumulator_2 = w_3_omega;\n                     * limb_accumulator_2 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_2 += w_2_omega;\n                     * limb_accumulator_2 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_2 += w_1_omega;\n                     * limb_accumulator_2 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_2 += w_4;\n                     * limb_accumulator_2 *= SUBLIMB_SHIFT;\n                     * limb_accumulator_2 += w_3;\n                     * limb_accumulator_2 -= w_4_omega;\n                     * limb_accumulator_2 *= q_m;\n                     */\n                    let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)\n                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p)\n                    limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)\n                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p)\n                    limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)\n                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p)\n                    limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)\n                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p)\n                    limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)\n                    limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p)\n\n                    mstore(\n                        AUX_LIMB_ACCUMULATOR_EVALUATION,\n                        mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p)\n                    )\n                }\n\n                {\n                    /**\n                     * memory_record_check = w_3;\n                     * memory_record_check *= eta;\n                     * memory_record_check += w_2;\n                     * memory_record_check *= eta;\n                     * memory_record_check += w_1;\n                     * memory_record_check *= eta;\n                     * memory_record_check += q_c;\n                     *\n                     * partial_record_check = memory_record_check;\n                     *\n                     * memory_record_check -= w_4;\n                     */\n\n                    let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p)\n                    memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p)\n                    memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)\n                    memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p)\n                    memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)\n                    memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p)\n\n                    let partial_record_check := memory_record_check\n                    memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p)\n\n                    mstore(AUX_MEMORY_EVALUATION, memory_record_check)\n\n                    // index_delta = w_1_omega - w_1\n                    let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)\n                    // record_delta = w_4_omega - w_4\n                    let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)\n                    // index_is_monotonically_increasing = index_delta * (index_delta - 1)\n                    let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p)\n\n                    // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta)\n                    let adjacent_values_match_if_adjacent_indices_match :=\n                        mulmod(record_delta, addmod(1, sub(p, index_delta), p), p)\n\n                    // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check\n                    mstore(\n                        AUX_ROM_CONSISTENCY_EVALUATION,\n                        addmod(\n                            mulmod(\n                                addmod(\n                                    mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p),\n                                    index_is_monotonically_increasing,\n                                    p\n                                ),\n                                mload(C_ALPHA_LOC),\n                                p\n                            ),\n                            memory_record_check,\n                            p\n                        )\n                    )\n\n                    {\n                        /**\n                         * next_gate_access_type = w_3_omega;\n                         * next_gate_access_type *= eta;\n                         * next_gate_access_type += w_2_omega;\n                         * next_gate_access_type *= eta;\n                         * next_gate_access_type += w_1_omega;\n                         * next_gate_access_type *= eta;\n                         * next_gate_access_type = w_4_omega - next_gate_access_type;\n                         */\n                        let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p)\n                        next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p)\n                        next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)\n                        next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p)\n                        next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)\n                        next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p)\n\n                        // value_delta = w_3_omega - w_3\n                        let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)\n                        //  adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type);\n\n                        let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation :=\n                            mulmod(\n                                addmod(1, sub(p, index_delta), p),\n                                mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p),\n                                p\n                            )\n\n                        // AUX_RAM_CONSISTENCY_EVALUATION\n\n                        /**\n                         * access_type = w_4 - partial_record_check\n                         * access_check = access_type^2 - access_type\n                         * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type\n                         * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation;\n                         * RAM_consistency_check_identity *= alpha;\n                         * RAM_consistency_check_identity += index_is_monotonically_increasing;\n                         * RAM_consistency_check_identity *= alpha;\n                         * RAM_consistency_check_identity += next_gate_access_type_is_boolean;\n                         * RAM_consistency_check_identity *= alpha;\n                         * RAM_consistency_check_identity += access_check;\n                         */\n\n                        let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p)\n                        let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p)\n                        let next_gate_access_type_is_boolean :=\n                            mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p)\n                        let RAM_cci :=\n                            mulmod(\n                                adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation,\n                                mload(C_ALPHA_LOC),\n                                p\n                            )\n                        RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p)\n                        RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)\n                        RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p)\n                        RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)\n                        RAM_cci := addmod(RAM_cci, access_check, p)\n\n                        mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci)\n                    }\n\n                    {\n                        // timestamp_delta = w_2_omega - w_2\n                        let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)\n\n                        // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3\n                        let RAM_timestamp_check_identity :=\n                            addmod(\n                                mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p\n                            )\n\n                        /**\n                         * memory_identity = ROM_consistency_check_identity * q_2;\n                         * memory_identity += RAM_timestamp_check_identity * q_4;\n                         * memory_identity += memory_record_check * q_m;\n                         * memory_identity *= q_1;\n                         * memory_identity += (RAM_consistency_check_identity * q_arith);\n                         *\n                         * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity;\n                         * auxiliary_identity *= q_aux;\n                         * auxiliary_identity *= alpha_base;\n                         */\n                        let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p)\n                        memory_identity :=\n                            addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p)\n                        memory_identity :=\n                            addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p)\n                        memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p)\n                        memory_identity :=\n                            addmod(\n                                memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p\n                            )\n\n                        let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p)\n                        auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p)\n                        auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p)\n                        auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p)\n\n                        mstore(AUX_IDENTITY, auxiliary_identity)\n\n                        // update alpha\n                        mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))\n                    }\n                }\n            }\n\n            {\n                /**\n                 * quotient = ARITHMETIC_IDENTITY\n                 * quotient += PERMUTATION_IDENTITY\n                 * quotient += PLOOKUP_IDENTITY\n                 * quotient += SORT_IDENTITY\n                 * quotient += ELLIPTIC_IDENTITY\n                 * quotient += AUX_IDENTITY\n                 * quotient *= ZERO_POLY_INVERSE\n                 */\n                mstore(\n                    QUOTIENT_EVAL_LOC,\n                    mulmod(\n                        addmod(\n                            addmod(\n                                addmod(\n                                    addmod(\n                                        addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p),\n                                        mload(ARITHMETIC_IDENTITY),\n                                        p\n                                    ),\n                                    mload(SORT_IDENTITY),\n                                    p\n                                ),\n                                mload(ELLIPTIC_IDENTITY),\n                                p\n                            ),\n                            mload(AUX_IDENTITY),\n                            p\n                        ),\n                        mload(ZERO_POLY_INVERSE_LOC),\n                        p\n                    )\n                )\n            }\n\n            /**\n             * GENERATE NU AND SEPARATOR CHALLENGES\n             */\n            {\n                let current_challenge := mload(C_CURRENT_LOC)\n                // get a calldata pointer that points to the start of the data we want to copy\n                let calldata_ptr := add(calldataload(0x04), 0x24)\n\n                calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH)\n\n                mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge)\n                mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC))\n                calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH)\n\n                // hash length = (0x20 + num field elements), we include the previous challenge in the hash\n                let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40))\n\n                mstore(C_V0_LOC, mod(challenge, p))\n                // We need THIRTY-ONE independent nu challenges!\n                mstore(0x00, challenge)\n                mstore8(0x20, 0x01)\n                mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x02)\n                mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x03)\n                mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x04)\n                mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x05)\n                mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x06)\n                mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x07)\n                mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x08)\n                mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x09)\n                mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x0a)\n                mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x0b)\n                mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x0c)\n                mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x0d)\n                mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x0e)\n                mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x0f)\n                mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x10)\n                mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x11)\n                mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x12)\n                mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x13)\n                mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x14)\n                mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x15)\n                mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x16)\n                mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x17)\n                mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x18)\n                mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x19)\n                mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x1a)\n                mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x1b)\n                mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x1c)\n                mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p))\n                mstore8(0x20, 0x1d)\n                mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p))\n\n                // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change?\n                mstore8(0x20, 0x1d)\n                challenge := keccak256(0x00, 0x21)\n                mstore(C_V30_LOC, mod(challenge, p))\n\n                // separator\n                mstore(0x00, challenge)\n                mstore(0x20, mload(PI_Z_Y_LOC))\n                mstore(0x40, mload(PI_Z_X_LOC))\n                mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))\n                mstore(0x80, mload(PI_Z_OMEGA_X_LOC))\n\n                mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p))\n            }\n\n            let success := 0\n            // VALIDATE T1\n            {\n                let x := mload(T1_X_LOC)\n                let y := mload(T1_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(ACCUMULATOR_X_LOC, x)\n                mstore(add(ACCUMULATOR_X_LOC, 0x20), y)\n            }\n            // VALIDATE T2\n            {\n                let x := mload(T2_X_LOC) // 0x1400\n                let y := mload(T2_Y_LOC) // 0x1420\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mload(ZETA_POW_N_LOC))\n            // accumulator_2 = [T2].zeta^n\n            success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)\n            // accumulator = [T1] + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE T3\n            {\n                let x := mload(T3_X_LOC)\n                let y := mload(T3_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p))\n            // accumulator_2 = [T3].zeta^{2n}\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE T4\n            {\n                let x := mload(T4_X_LOC)\n                let y := mload(T4_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p))\n            // accumulator_2 = [T4].zeta^{3n}\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE W1\n            {\n                let x := mload(W1_X_LOC)\n                let y := mload(W1_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p))\n            // accumulator_2 = v0.(u + 1).[W1]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE W2\n            {\n                let x := mload(W2_X_LOC)\n                let y := mload(W2_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p))\n            // accumulator_2 = v1.(u + 1).[W2]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE W3\n            {\n                let x := mload(W3_X_LOC)\n                let y := mload(W3_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p))\n            // accumulator_2 = v2.(u + 1).[W3]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE W4\n            {\n                let x := mload(W4_X_LOC)\n                let y := mload(W4_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p))\n            // accumulator_2 = v3.(u + 1).[W4]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE S\n            {\n                let x := mload(S_X_LOC)\n                let y := mload(S_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p))\n            // accumulator_2 = v4.(u + 1).[S]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE Z\n            {\n                let x := mload(Z_X_LOC)\n                let y := mload(Z_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p))\n            // accumulator_2 = v5.(u + 1).[Z]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // VALIDATE Z_LOOKUP\n            {\n                let x := mload(Z_LOOKUP_X_LOC)\n                let y := mload(Z_LOOKUP_Y_LOC)\n                let xx := mulmod(x, x, q)\n                // validate on curve\n                if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                    mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n                mstore(0x00, x)\n                mstore(0x20, y)\n            }\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p))\n            // accumulator_2 = v6.(u + 1).[Z_LOOKUP]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE Q1\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(Q1_X_LOC))\n            mstore(0x20, mload(Q1_Y_LOC))\n            mstore(0x40, mload(C_V7_LOC))\n            // accumulator_2 = v7.[Q1]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE Q2\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(Q2_X_LOC))\n            mstore(0x20, mload(Q2_Y_LOC))\n            mstore(0x40, mload(C_V8_LOC))\n            // accumulator_2 = v8.[Q2]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE Q3\n            \n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(Q3_X_LOC))\n            mstore(0x20, mload(Q3_Y_LOC))\n            mstore(0x40, mload(C_V9_LOC))\n            // accumulator_2 = v9.[Q3]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE Q4\n            \n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(Q4_X_LOC))\n            mstore(0x20, mload(Q4_Y_LOC))\n            mstore(0x40, mload(C_V10_LOC))\n            // accumulator_2 = v10.[Q4]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE QM\n            \n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(QM_X_LOC))\n            mstore(0x20, mload(QM_Y_LOC))\n            mstore(0x40, mload(C_V11_LOC))\n            // accumulator_2 = v11.[Q;]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE QC\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(QC_X_LOC))\n            mstore(0x20, mload(QC_Y_LOC))\n            mstore(0x40, mload(C_V12_LOC))\n            // accumulator_2 = v12.[QC]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE QARITH\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(QARITH_X_LOC))\n            mstore(0x20, mload(QARITH_Y_LOC))\n            mstore(0x40, mload(C_V13_LOC))\n            // accumulator_2 = v13.[QARITH]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE QSORT\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(QSORT_X_LOC))\n            mstore(0x20, mload(QSORT_Y_LOC))\n            mstore(0x40, mload(C_V14_LOC))\n            // accumulator_2 = v14.[QSORT]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE QELLIPTIC\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(QELLIPTIC_X_LOC))\n            mstore(0x20, mload(QELLIPTIC_Y_LOC))\n            mstore(0x40, mload(C_V15_LOC))\n            // accumulator_2 = v15.[QELLIPTIC]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE QAUX\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(QAUX_X_LOC))\n            mstore(0x20, mload(QAUX_Y_LOC))\n            mstore(0x40, mload(C_V16_LOC))\n            // accumulator_2 = v15.[Q_AUX]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE SIGMA1\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(SIGMA1_X_LOC))\n            mstore(0x20, mload(SIGMA1_Y_LOC))\n            mstore(0x40, mload(C_V17_LOC))\n            // accumulator_2 = v17.[sigma1]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE SIGMA2\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(SIGMA2_X_LOC))\n            mstore(0x20, mload(SIGMA2_Y_LOC))\n            mstore(0x40, mload(C_V18_LOC))\n            // accumulator_2 = v18.[sigma2]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE SIGMA3\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(SIGMA3_X_LOC))\n            mstore(0x20, mload(SIGMA3_Y_LOC))\n            mstore(0x40, mload(C_V19_LOC))\n            // accumulator_2 = v19.[sigma3]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE SIGMA4\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(SIGMA4_X_LOC))\n            mstore(0x20, mload(SIGMA4_Y_LOC))\n            mstore(0x40, mload(C_V20_LOC))\n            // accumulator_2 = v20.[sigma4]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE TABLE1\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(TABLE1_X_LOC))\n            mstore(0x20, mload(TABLE1_Y_LOC))\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p))\n            // accumulator_2 = u.[table1]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE TABLE2\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(TABLE2_X_LOC))\n            mstore(0x20, mload(TABLE2_Y_LOC))\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p))\n            // accumulator_2 = u.[table2]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE TABLE3\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(TABLE3_X_LOC))\n            mstore(0x20, mload(TABLE3_Y_LOC))\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p))\n            // accumulator_2 = u.[table3]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE TABLE4\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(TABLE4_X_LOC))\n            mstore(0x20, mload(TABLE4_Y_LOC))\n            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p))\n            // accumulator_2 = u.[table4]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE TABLE_TYPE\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(TABLE_TYPE_X_LOC))\n            mstore(0x20, mload(TABLE_TYPE_Y_LOC))\n            mstore(0x40, mload(C_V25_LOC))\n            // accumulator_2 = v25.[TableType]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE ID1\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(ID1_X_LOC))\n            mstore(0x20, mload(ID1_Y_LOC))\n            mstore(0x40, mload(C_V26_LOC))\n            // accumulator_2 = v26.[ID1]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE ID2\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(ID2_X_LOC))\n            mstore(0x20, mload(ID2_Y_LOC))\n            mstore(0x40, mload(C_V27_LOC))\n            // accumulator_2 = v27.[ID2]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE ID3\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(ID3_X_LOC))\n            mstore(0x20, mload(ID3_Y_LOC))\n            mstore(0x40, mload(C_V28_LOC))\n            // accumulator_2 = v28.[ID3]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            // ACCUMULATE ID4\n\n            // Verification key fields verified to be on curve at contract deployment\n            mstore(0x00, mload(ID4_X_LOC))\n            mstore(0x20, mload(ID4_Y_LOC))\n            mstore(0x40, mload(C_V29_LOC))\n            // accumulator_2 = v29.[ID4]\n            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n            // accumulator = accumulator + accumulator_2\n            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n            /**\n             * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER\n             */\n            {\n                /**\n                 * batch_evaluation = v0 * (w_1_omega * u + w_1_eval)\n                 * batch_evaluation += v1 * (w_2_omega * u + w_2_eval)\n                 * batch_evaluation += v2 * (w_3_omega * u + w_3_eval)\n                 * batch_evaluation += v3 * (w_4_omega * u + w_4_eval)\n                 * batch_evaluation += v4 * (s_omega_eval * u + s_eval)\n                 * batch_evaluation += v5 * (z_omega_eval * u + z_eval)\n                 * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval)\n                 */\n                let batch_evaluation :=\n                    mulmod(\n                        mload(C_V0_LOC),\n                        addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V1_LOC),\n                            addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V2_LOC),\n                            addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V3_LOC),\n                            addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V4_LOC),\n                            addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V5_LOC),\n                            addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V6_LOC),\n                            addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n\n                /**\n                 * batch_evaluation += v7 * Q1_EVAL\n                 * batch_evaluation += v8 * Q2_EVAL\n                 * batch_evaluation += v9 * Q3_EVAL\n                 * batch_evaluation += v10 * Q4_EVAL\n                 * batch_evaluation += v11 * QM_EVAL\n                 * batch_evaluation += v12 * QC_EVAL\n                 * batch_evaluation += v13 * QARITH_EVAL\n                 * batch_evaluation += v14 * QSORT_EVAL_LOC\n                 * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC\n                 * batch_evaluation += v16 * QAUX_EVAL_LOC\n                 * batch_evaluation += v17 * SIGMA1_EVAL_LOC\n                 * batch_evaluation += v18 * SIGMA2_EVAL_LOC\n                 * batch_evaluation += v19 * SIGMA3_EVAL_LOC\n                 * batch_evaluation += v20 * SIGMA4_EVAL_LOC\n                 */\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p)\n\n                /**\n                 * batch_evaluation += v21 * (table1(zw) * u + table1(z))\n                 * batch_evaluation += v22 * (table2(zw) * u + table2(z))\n                 * batch_evaluation += v23 * (table3(zw) * u + table3(z))\n                 * batch_evaluation += v24 * (table4(zw) * u + table4(z))\n                 * batch_evaluation += v25 * table_type_eval\n                 * batch_evaluation += v26 * id1_eval\n                 * batch_evaluation += v27 * id2_eval\n                 * batch_evaluation += v28 * id3_eval\n                 * batch_evaluation += v29 * id4_eval\n                 * batch_evaluation += quotient_eval\n                 */\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V21_LOC),\n                            addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V22_LOC),\n                            addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V23_LOC),\n                            addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation :=\n                    addmod(\n                        batch_evaluation,\n                        mulmod(\n                            mload(C_V24_LOC),\n                            addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p),\n                            p\n                        ),\n                        p\n                    )\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p)\n                batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p)\n\n                mstore(0x00, 0x01) // [1].x\n                mstore(0x20, 0x02) // [1].y\n                mstore(0x40, sub(p, batch_evaluation))\n                // accumulator_2 = -[1].(batch_evaluation)\n                success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n                // accumulator = accumulator + accumulator_2\n                success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n                if iszero(success) {\n                    mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n            }\n\n            /**\n             * PERFORM PAIRING PREAMBLE\n             */\n            {\n                let u := mload(C_U_LOC)\n                let zeta := mload(C_ZETA_LOC)\n                // VALIDATE PI_Z\n                {\n                    let x := mload(PI_Z_X_LOC)\n                    let y := mload(PI_Z_Y_LOC)\n                    let xx := mulmod(x, x, q)\n                    // validate on curve\n                    if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                        mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                        revert(0x00, 0x04)\n                    }\n                    mstore(0x00, x)\n                    mstore(0x20, y)\n                }\n                // compute zeta.[PI_Z] and add into accumulator\n                mstore(0x40, zeta)\n                success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)\n                // accumulator = accumulator + accumulator_2\n                success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))\n\n                // VALIDATE PI_Z_OMEGA\n                {\n                    let x := mload(PI_Z_OMEGA_X_LOC)\n                    let y := mload(PI_Z_OMEGA_Y_LOC)\n                    let xx := mulmod(x, x, q)\n                    // validate on curve\n                    if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                        mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                        revert(0x00, 0x04)\n                    }\n                    mstore(0x00, x)\n                    mstore(0x20, y)\n                }\n                mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p))\n                // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA]\n                success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))\n                // PAIRING_RHS = accumulator + accumulator_2\n                success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40))\n\n                mstore(0x00, mload(PI_Z_X_LOC))\n                mstore(0x20, mload(PI_Z_Y_LOC))\n                mstore(0x40, mload(PI_Z_OMEGA_X_LOC))\n                mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))\n                mstore(0x80, u)\n                success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40))\n                // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u\n                success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))\n                // negate lhs y-coordinate\n                mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC)))\n\n                if mload(CONTAINS_RECURSIVE_PROOF_LOC) {\n                    // VALIDATE RECURSIVE P1\n                    {\n                        let x := mload(RECURSIVE_P1_X_LOC)\n                        let y := mload(RECURSIVE_P1_Y_LOC)\n                        let xx := mulmod(x, x, q)\n                        // validate on curve\n                        if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                            mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                            revert(0x00, 0x04)\n                        }\n                        mstore(0x00, x)\n                        mstore(0x20, y)\n                    }\n\n                    // compute u.u.[recursive_p1] and write into 0x60\n                    mstore(0x40, mulmod(u, u, p))\n                    success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40))\n                    // VALIDATE RECURSIVE P2\n                    {\n                        let x := mload(RECURSIVE_P2_X_LOC)\n                        let y := mload(RECURSIVE_P2_Y_LOC)\n                        let xx := mulmod(x, x, q)\n                        // validate on curve\n                        if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) {\n                            mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR)\n                            revert(0x00, 0x04)\n                        }\n                        mstore(0x00, x)\n                        mstore(0x20, y)\n                    }\n                    // compute u.u.[recursive_p2] and write into 0x00\n                    // 0x40 still contains u*u\n                    success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40))\n\n                    // compute u.u.[recursiveP1] + rhs and write into rhs\n                    mstore(0xa0, mload(PAIRING_RHS_X_LOC))\n                    mstore(0xc0, mload(PAIRING_RHS_Y_LOC))\n                    success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40))\n\n                    // compute u.u.[recursiveP2] + lhs and write into lhs\n                    mstore(0x40, mload(PAIRING_LHS_X_LOC))\n                    mstore(0x60, mload(PAIRING_LHS_Y_LOC))\n                    success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))\n                }\n\n                if iszero(success) {\n                    mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n            }\n\n            /**\n             * PERFORM PAIRING\n             */\n            {\n                // rhs paired with [1]_2\n                // lhs paired with [x]_2\n\n                mstore(0x00, mload(PAIRING_RHS_X_LOC))\n                mstore(0x20, mload(PAIRING_RHS_Y_LOC))\n                mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2\n                mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed)\n                mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b)\n                mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa)\n\n                mstore(0xc0, mload(PAIRING_LHS_X_LOC))\n                mstore(0xe0, mload(PAIRING_LHS_Y_LOC))\n                mstore(0x100, mload(G2X_X0_LOC))\n                mstore(0x120, mload(G2X_X1_LOC))\n                mstore(0x140, mload(G2X_Y0_LOC))\n                mstore(0x160, mload(G2X_Y1_LOC))\n\n                success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20)\n                if iszero(and(success, mload(0x00))) {\n                    mstore(0x0, PAIRING_FAILED_SELECTOR)\n                    revert(0x00, 0x04)\n                }\n            }\n\n            {\n                mstore(0x00, 0x01)\n                return(0x00, 0x20) // Proof succeeded!\n            }\n        }\n    }\n}\n\ncontract UniswapSwapVerifier is BaseUltraVerifier {\n    function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) {\n        return UltraVerificationKey.verificationKeyHash();\n    }\n\n    function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) {\n        UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc);\n    }\n}\n"
      }
    }
  }}