Sepolia Testnet

Contract

0x8B12bC2e5E30DE6Da2eb3960D65F3FAC6d33f026

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Value
0x6080604043150152023-09-18 17:57:48274 days ago1695059868IN
 Create: UltraVerifier
0 ETH0.006355332.50002208

Advanced mode:
Parent Transaction Hash Block From To Value
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UltraVerifier

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Apache-2.0 license
/**
 *Submitted for verification at Etherscan.io on 2023-09-18
*/

// Verification Key Hash: d11f99e40c55d0ef202afc9d6497a56340bb8a86b5ceb40f13c6d96d72d9fcca
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec
pragma solidity >=0.8.4;

library UltraVerificationKey {
    function verificationKeyHash() internal pure returns(bytes32) {
        return 0xd11f99e40c55d0ef202afc9d6497a56340bb8a86b5ceb40f13c6d96d72d9fcca;
    }

    function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure {
        assembly {
            mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000020000) // vk.circuit_size
            mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000037) // vk.num_inputs
            mstore(add(_vk, 0x40), 0x1bf82deba7d74902c3708cc6e70e61f30512eca95655210e276e5858ce8f58e5) // vk.work_root
            mstore(add(_vk, 0x60), 0x30643640b9f82f90e83b698e5ea6179c7c05542e859533b48b9953a2f5360801) // vk.domain_inverse
            mstore(add(_vk, 0x80), 0x245285cdf6c55535c4c72ecc89b3806ab342cd6e01bbb82b0c5c0113cba4a211) // vk.Q1.x
            mstore(add(_vk, 0xa0), 0x1b565aa264e9d606df12185b82e6576a58d4513d864ed651927e961e461dcc86) // vk.Q1.y
            mstore(add(_vk, 0xc0), 0x272dc56c0559a6089e4c3b48edd6c4c80fa911f5c041cbe3af06f7614bbbb43a) // vk.Q2.x
            mstore(add(_vk, 0xe0), 0x18e69137e65a9875f4ee14c4880f5d0506defdade9186ba227b1e46a7652c0ed) // vk.Q2.y
            mstore(add(_vk, 0x100), 0x1f7131f4d583fc283d61e1c1053c70ab3ae7afbb4b2b4b95fbbd1c1430dabc16) // vk.Q3.x
            mstore(add(_vk, 0x120), 0x2a787bbadc7214d359b0feeabb1fdd0722801bdb1383aceeac392d3b8e4c4065) // vk.Q3.y
            mstore(add(_vk, 0x140), 0x1735f148bd3f021f7e5401fb512f967181d442b239dd607d741d9924d9753ed4) // vk.Q4.x
            mstore(add(_vk, 0x160), 0x19da04c1072f90dc7bdc09fc92b41b0f89d97347b8021ddd54fb8fba967b2331) // vk.Q4.y
            mstore(add(_vk, 0x180), 0x031ad7e57c0c7113b369040cbfc3dd8de50d32e976e183e1c933096bef9c6a7f) // vk.Q_M.x
            mstore(add(_vk, 0x1a0), 0x0f571b6887f7af84ec8c11b3d00705d218fd60433cf7f407ff610bc9e874017d) // vk.Q_M.y
            mstore(add(_vk, 0x1c0), 0x2dddf1ada8a8d49f4437fbb93af9165e4af883c41a7ade0c4d714e11242703c5) // vk.Q_C.x
            mstore(add(_vk, 0x1e0), 0x21ad6325b7bc4c8223416ba9d17ccecc6d5667cfe176791a5f02c6df49c9af5b) // vk.Q_C.y
            mstore(add(_vk, 0x200), 0x245bf8a517b30344ac2e9c1387e2ffbfcb15877ccf9dc167f0c810d6cf763317) // vk.Q_ARITHMETIC.x
            mstore(add(_vk, 0x220), 0x2f200231a08e7beeffde231718ab0ab8dc9dbe96e0929a07d7adb342d012978a) // vk.Q_ARITHMETIC.y
            mstore(add(_vk, 0x240), 0x23ac6d2f41b030d51bbc19ccfb4648d70e875206a22124faddfa4d3fbd135278) // vk.QSORT.x
            mstore(add(_vk, 0x260), 0x2d24acb1262a55fcef579f9249ddae57c5a20a84ec61d37fb845599824bb317a) // vk.QSORT.y
            mstore(add(_vk, 0x280), 0x2e438eb058a779a5ad4135fd7e14d1145a038cc260c09cc8622bc19b90cf5dbe) // vk.Q_ELLIPTIC.x
            mstore(add(_vk, 0x2a0), 0x288504c94c6277a8b5004fc5dde949f0ce8c895e56d52e62d4f1c9175b19b45e) // vk.Q_ELLIPTIC.y
            mstore(add(_vk, 0x2c0), 0x1414af76247139fa9e8fef8b393a3e03227ee3a6fedb1e55f5db82cb2352782a) // vk.Q_AUX.x
            mstore(add(_vk, 0x2e0), 0x2c7895a68d2fab5b2bce4d7703daebf9011e63d675bc6898c7f06087d6d83d99) // vk.Q_AUX.y
            mstore(add(_vk, 0x300), 0x18b742204f0348b5c1b38c8a1a3698f99696f77b0739572ed32f5ff735587526) // vk.SIGMA1.x
            mstore(add(_vk, 0x320), 0x180c4419454e91a4cf890444c937e108ffce7e3f88d86fcff3753c38b0a23f66) // vk.SIGMA1.y
            mstore(add(_vk, 0x340), 0x0a6ff425e08220154841bf2ca49c216137315a40781c7df12ce13543ab59a4cd) // vk.SIGMA2.x
            mstore(add(_vk, 0x360), 0x1ae3a99295d617eecf7abde22269ebf78cc7060000dcb08a8c37d00f9e630a9b) // vk.SIGMA2.y
            mstore(add(_vk, 0x380), 0x2132af6633a1cc574d02e157dad9a69b22c1f5caa5bbcc22db5a95132e3bf076) // vk.SIGMA3.x
            mstore(add(_vk, 0x3a0), 0x2e79886ca28210ee429fd38d3727f549f2f91e1dee91e5f875f8b588d367b527) // vk.SIGMA3.y
            mstore(add(_vk, 0x3c0), 0x00c465601b3d03dffc34f62e0f11de17542c4a745b7a878ce754c1f4ad82bfae) // vk.SIGMA4.x
            mstore(add(_vk, 0x3e0), 0x0060c9633269601f6fcb01b6d26d46ee93055f807a2a1c9e7c33d186f04f65f8) // vk.SIGMA4.y
            mstore(add(_vk, 0x400), 0x1f085b2095ee26145e167f353ef9a02dde005b3ba11bf60add10bdd9c00e7643) // vk.TABLE1.x
            mstore(add(_vk, 0x420), 0x0748759c43af1624acf605b6a23ebba01173cd346730c934d5fb7edd48413f94) // vk.TABLE1.y
            mstore(add(_vk, 0x440), 0x2c8d2b9623692ab46021a60209f7148458ecb2ccdbbd766251f463ca7c53489a) // vk.TABLE2.x
            mstore(add(_vk, 0x460), 0x1aefa543256fc4b49dc193383f0156f7c331a2b89d0a0b5938a2fe2abe136d19) // vk.TABLE2.y
            mstore(add(_vk, 0x480), 0x058ea36a362c899e3304278eca9a52fa74b07588d35cc5583278237cbbb53d68) // vk.TABLE3.x
            mstore(add(_vk, 0x4a0), 0x2afc5a5c85ca7b8fdac8a2b082096621e184e5a00a5cf1d481e28ad8071a691a) // vk.TABLE3.y
            mstore(add(_vk, 0x4c0), 0x14864cbfc194228094a325c4abf8260dbdca65e4883fce1425ec2933843b6737) // vk.TABLE4.x
            mstore(add(_vk, 0x4e0), 0x1489390b9b42c540c675cfea8acb88ceebe8c678f21ee8e8bee12af884fc1c3d) // vk.TABLE4.y
            mstore(add(_vk, 0x500), 0x2e6f974274a8b0d7c22721399c87384f68404226f622f0e50f9182fe4a9c7af3) // vk.TABLE_TYPE.x
            mstore(add(_vk, 0x520), 0x1bd608ba7bca523c9564c26bb23e27553fa0a0071e77a4123590e98b57860f09) // vk.TABLE_TYPE.y
            mstore(add(_vk, 0x540), 0x1106ffa0e5b65066a1e6f54849a38c0fa40cd0f86edfb8c53de73175aa1a0aaa) // vk.ID1.x
            mstore(add(_vk, 0x560), 0x04caf81aa2aa53dd6a58b56d058005810cf634fbef2fd7945ee29aaa8744414a) // vk.ID1.y
            mstore(add(_vk, 0x580), 0x0acafc98985553ff731f444d22822ca2054385216d1e9f003b84868dfef67f5a) // vk.ID2.x
            mstore(add(_vk, 0x5a0), 0x059fc7ed336de83aac1273db4f51760b61cba1a42f3495738653ab46370dde76) // vk.ID2.y
            mstore(add(_vk, 0x5c0), 0x2d6688fcab60e29a560b4e4e03e0cc0d9e43dfb8d5b192e722d72a0e3adafdaf) // vk.ID3.x
            mstore(add(_vk, 0x5e0), 0x02bbd2a1bd7674a5b4e764db185aa85418f61b44c800329a3c43893f07a3c35a) // vk.ID3.y
            mstore(add(_vk, 0x600), 0x2e68f5b79c21422d3a849acc310202e3507f9ffd78d24d930c2b764393cd3e8f) // vk.ID4.x
            mstore(add(_vk, 0x620), 0x018e8379fcfaa214c9b07a4d500b14c6b03f2e218423a61c59d6e569a6a77a6e) // vk.ID4.y
            mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof
            mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices
            mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 
            mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 
            mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 
            mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 
            mstore(_omegaInverseLoc, 0x244cf010c43ca87237d8b00bf9dd50c4c01c7f086bd4e8c920e75251d96f0d22) // vk.work_root_inverse
        }
    }
}

/**
 * @title Ultra Plonk proof verification contract
 * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified
 */
abstract contract BaseUltraVerifier {
    // VERIFICATION KEY MEMORY LOCATIONS
    uint256 internal constant N_LOC = 0x380;
    uint256 internal constant NUM_INPUTS_LOC = 0x3a0;
    uint256 internal constant OMEGA_LOC = 0x3c0;
    uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0;
    uint256 internal constant Q1_X_LOC = 0x400;
    uint256 internal constant Q1_Y_LOC = 0x420;
    uint256 internal constant Q2_X_LOC = 0x440;
    uint256 internal constant Q2_Y_LOC = 0x460;
    uint256 internal constant Q3_X_LOC = 0x480;
    uint256 internal constant Q3_Y_LOC = 0x4a0;
    uint256 internal constant Q4_X_LOC = 0x4c0;
    uint256 internal constant Q4_Y_LOC = 0x4e0;
    uint256 internal constant QM_X_LOC = 0x500;
    uint256 internal constant QM_Y_LOC = 0x520;
    uint256 internal constant QC_X_LOC = 0x540;
    uint256 internal constant QC_Y_LOC = 0x560;
    uint256 internal constant QARITH_X_LOC = 0x580;
    uint256 internal constant QARITH_Y_LOC = 0x5a0;
    uint256 internal constant QSORT_X_LOC = 0x5c0;
    uint256 internal constant QSORT_Y_LOC = 0x5e0;
    uint256 internal constant QELLIPTIC_X_LOC = 0x600;
    uint256 internal constant QELLIPTIC_Y_LOC = 0x620;
    uint256 internal constant QAUX_X_LOC = 0x640;
    uint256 internal constant QAUX_Y_LOC = 0x660;
    uint256 internal constant SIGMA1_X_LOC = 0x680;
    uint256 internal constant SIGMA1_Y_LOC = 0x6a0;
    uint256 internal constant SIGMA2_X_LOC = 0x6c0;
    uint256 internal constant SIGMA2_Y_LOC = 0x6e0;
    uint256 internal constant SIGMA3_X_LOC = 0x700;
    uint256 internal constant SIGMA3_Y_LOC = 0x720;
    uint256 internal constant SIGMA4_X_LOC = 0x740;
    uint256 internal constant SIGMA4_Y_LOC = 0x760;
    uint256 internal constant TABLE1_X_LOC = 0x780;
    uint256 internal constant TABLE1_Y_LOC = 0x7a0;
    uint256 internal constant TABLE2_X_LOC = 0x7c0;
    uint256 internal constant TABLE2_Y_LOC = 0x7e0;
    uint256 internal constant TABLE3_X_LOC = 0x800;
    uint256 internal constant TABLE3_Y_LOC = 0x820;
    uint256 internal constant TABLE4_X_LOC = 0x840;
    uint256 internal constant TABLE4_Y_LOC = 0x860;
    uint256 internal constant TABLE_TYPE_X_LOC = 0x880;
    uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0;
    uint256 internal constant ID1_X_LOC = 0x8c0;
    uint256 internal constant ID1_Y_LOC = 0x8e0;
    uint256 internal constant ID2_X_LOC = 0x900;
    uint256 internal constant ID2_Y_LOC = 0x920;
    uint256 internal constant ID3_X_LOC = 0x940;
    uint256 internal constant ID3_Y_LOC = 0x960;
    uint256 internal constant ID4_X_LOC = 0x980;
    uint256 internal constant ID4_Y_LOC = 0x9a0;
    uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0;
    uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0;
    uint256 internal constant G2X_X0_LOC = 0xa00;
    uint256 internal constant G2X_X1_LOC = 0xa20;
    uint256 internal constant G2X_Y0_LOC = 0xa40;
    uint256 internal constant G2X_Y1_LOC = 0xa60;

    // ### PROOF DATA MEMORY LOCATIONS
    uint256 internal constant W1_X_LOC = 0x1200;
    uint256 internal constant W1_Y_LOC = 0x1220;
    uint256 internal constant W2_X_LOC = 0x1240;
    uint256 internal constant W2_Y_LOC = 0x1260;
    uint256 internal constant W3_X_LOC = 0x1280;
    uint256 internal constant W3_Y_LOC = 0x12a0;
    uint256 internal constant W4_X_LOC = 0x12c0;
    uint256 internal constant W4_Y_LOC = 0x12e0;
    uint256 internal constant S_X_LOC = 0x1300;
    uint256 internal constant S_Y_LOC = 0x1320;
    uint256 internal constant Z_X_LOC = 0x1340;
    uint256 internal constant Z_Y_LOC = 0x1360;
    uint256 internal constant Z_LOOKUP_X_LOC = 0x1380;
    uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0;
    uint256 internal constant T1_X_LOC = 0x13c0;
    uint256 internal constant T1_Y_LOC = 0x13e0;
    uint256 internal constant T2_X_LOC = 0x1400;
    uint256 internal constant T2_Y_LOC = 0x1420;
    uint256 internal constant T3_X_LOC = 0x1440;
    uint256 internal constant T3_Y_LOC = 0x1460;
    uint256 internal constant T4_X_LOC = 0x1480;
    uint256 internal constant T4_Y_LOC = 0x14a0;

    uint256 internal constant W1_EVAL_LOC = 0x1600;
    uint256 internal constant W2_EVAL_LOC = 0x1620;
    uint256 internal constant W3_EVAL_LOC = 0x1640;
    uint256 internal constant W4_EVAL_LOC = 0x1660;
    uint256 internal constant S_EVAL_LOC = 0x1680;
    uint256 internal constant Z_EVAL_LOC = 0x16a0;
    uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0;
    uint256 internal constant Q1_EVAL_LOC = 0x16e0;
    uint256 internal constant Q2_EVAL_LOC = 0x1700;
    uint256 internal constant Q3_EVAL_LOC = 0x1720;
    uint256 internal constant Q4_EVAL_LOC = 0x1740;
    uint256 internal constant QM_EVAL_LOC = 0x1760;
    uint256 internal constant QC_EVAL_LOC = 0x1780;
    uint256 internal constant QARITH_EVAL_LOC = 0x17a0;
    uint256 internal constant QSORT_EVAL_LOC = 0x17c0;
    uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0;
    uint256 internal constant QAUX_EVAL_LOC = 0x1800;
    uint256 internal constant TABLE1_EVAL_LOC = 0x1840;
    uint256 internal constant TABLE2_EVAL_LOC = 0x1860;
    uint256 internal constant TABLE3_EVAL_LOC = 0x1880;
    uint256 internal constant TABLE4_EVAL_LOC = 0x18a0;
    uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0;
    uint256 internal constant ID1_EVAL_LOC = 0x18e0;
    uint256 internal constant ID2_EVAL_LOC = 0x1900;
    uint256 internal constant ID3_EVAL_LOC = 0x1920;
    uint256 internal constant ID4_EVAL_LOC = 0x1940;
    uint256 internal constant SIGMA1_EVAL_LOC = 0x1960;
    uint256 internal constant SIGMA2_EVAL_LOC = 0x1980;
    uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0;
    uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0;
    uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0;
    uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000;
    uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020;
    uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040;
    uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060;
    uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080;
    uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0;
    uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0;
    uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0;
    uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100;
    uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120;

    uint256 internal constant PI_Z_X_LOC = 0x2300;
    uint256 internal constant PI_Z_Y_LOC = 0x2320;
    uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340;
    uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360;

    // Used for elliptic widget. These are alias names for wire + shifted wire evaluations
    uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC;
    uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC;
    uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC;
    uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC;
    uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC;
    uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC;
    uint256 internal constant QBETA_LOC = Q3_EVAL_LOC;
    uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC;
    uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC;

    // ### CHALLENGES MEMORY OFFSETS

    uint256 internal constant C_BETA_LOC = 0x2600;
    uint256 internal constant C_GAMMA_LOC = 0x2620;
    uint256 internal constant C_ALPHA_LOC = 0x2640;
    uint256 internal constant C_ETA_LOC = 0x2660;
    uint256 internal constant C_ETA_SQR_LOC = 0x2680;
    uint256 internal constant C_ETA_CUBE_LOC = 0x26a0;

    uint256 internal constant C_ZETA_LOC = 0x26c0;
    uint256 internal constant C_CURRENT_LOC = 0x26e0;
    uint256 internal constant C_V0_LOC = 0x2700;
    uint256 internal constant C_V1_LOC = 0x2720;
    uint256 internal constant C_V2_LOC = 0x2740;
    uint256 internal constant C_V3_LOC = 0x2760;
    uint256 internal constant C_V4_LOC = 0x2780;
    uint256 internal constant C_V5_LOC = 0x27a0;
    uint256 internal constant C_V6_LOC = 0x27c0;
    uint256 internal constant C_V7_LOC = 0x27e0;
    uint256 internal constant C_V8_LOC = 0x2800;
    uint256 internal constant C_V9_LOC = 0x2820;
    uint256 internal constant C_V10_LOC = 0x2840;
    uint256 internal constant C_V11_LOC = 0x2860;
    uint256 internal constant C_V12_LOC = 0x2880;
    uint256 internal constant C_V13_LOC = 0x28a0;
    uint256 internal constant C_V14_LOC = 0x28c0;
    uint256 internal constant C_V15_LOC = 0x28e0;
    uint256 internal constant C_V16_LOC = 0x2900;
    uint256 internal constant C_V17_LOC = 0x2920;
    uint256 internal constant C_V18_LOC = 0x2940;
    uint256 internal constant C_V19_LOC = 0x2960;
    uint256 internal constant C_V20_LOC = 0x2980;
    uint256 internal constant C_V21_LOC = 0x29a0;
    uint256 internal constant C_V22_LOC = 0x29c0;
    uint256 internal constant C_V23_LOC = 0x29e0;
    uint256 internal constant C_V24_LOC = 0x2a00;
    uint256 internal constant C_V25_LOC = 0x2a20;
    uint256 internal constant C_V26_LOC = 0x2a40;
    uint256 internal constant C_V27_LOC = 0x2a60;
    uint256 internal constant C_V28_LOC = 0x2a80;
    uint256 internal constant C_V29_LOC = 0x2aa0;
    uint256 internal constant C_V30_LOC = 0x2ac0;

    uint256 internal constant C_U_LOC = 0x2b00;

    // ### LOCAL VARIABLES MEMORY OFFSETS
    uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000;
    uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020;
    uint256 internal constant ZETA_POW_N_LOC = 0x3040;
    uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060;
    uint256 internal constant ZERO_POLY_LOC = 0x3080;
    uint256 internal constant L_START_LOC = 0x30a0;
    uint256 internal constant L_END_LOC = 0x30c0;
    uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0;

    uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100;
    uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120;
    uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140;

    uint256 internal constant ACCUMULATOR_X_LOC = 0x3160;
    uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180;
    uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0;
    uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0;
    uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0;
    uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200;
    uint256 internal constant PAIRING_RHS_X_LOC = 0x3220;
    uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240;

    // ### SUCCESS FLAG MEMORY LOCATIONS
    uint256 internal constant GRAND_PRODUCT_SUCCESS_FLAG = 0x3300;
    uint256 internal constant ARITHMETIC_TERM_SUCCESS_FLAG = 0x3020;
    uint256 internal constant BATCH_OPENING_SUCCESS_FLAG = 0x3340;
    uint256 internal constant OPENING_COMMITMENT_SUCCESS_FLAG = 0x3360;
    uint256 internal constant PAIRING_PREAMBLE_SUCCESS_FLAG = 0x3380;
    uint256 internal constant PAIRING_SUCCESS_FLAG = 0x33a0;
    uint256 internal constant RESULT_FLAG = 0x33c0;

    // misc stuff
    uint256 internal constant OMEGA_INVERSE_LOC = 0x3400;
    uint256 internal constant C_ALPHA_SQR_LOC = 0x3420;
    uint256 internal constant C_ALPHA_CUBE_LOC = 0x3440;
    uint256 internal constant C_ALPHA_QUAD_LOC = 0x3460;
    uint256 internal constant C_ALPHA_BASE_LOC = 0x3480;

    // ### RECURSION VARIABLE MEMORY LOCATIONS
    uint256 internal constant RECURSIVE_P1_X_LOC = 0x3500;
    uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3520;
    uint256 internal constant RECURSIVE_P2_X_LOC = 0x3540;
    uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3560;

    uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3580;

    // sub-identity storage
    uint256 internal constant PERMUTATION_IDENTITY = 0x3600;
    uint256 internal constant PLOOKUP_IDENTITY = 0x3620;
    uint256 internal constant ARITHMETIC_IDENTITY = 0x3640;
    uint256 internal constant SORT_IDENTITY = 0x3660;
    uint256 internal constant ELLIPTIC_IDENTITY = 0x3680;
    uint256 internal constant AUX_IDENTITY = 0x36a0;
    uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x36c0;
    uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x36e0;
    uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3700;
    uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3720;
    uint256 internal constant AUX_MEMORY_EVALUATION = 0x3740;

    uint256 internal constant QUOTIENT_EVAL_LOC = 0x3760;
    uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3780;

    // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time
    uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x37a0;
    uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x37c0;
    uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0;

    bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6;
    bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f;
    bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc;
    bytes4 internal constant EC_SCALAR_MUL_FAILURE_SELECTOR = 0xf755f369;
    bytes4 internal constant PROOF_FAILURE_SELECTOR = 0x0711fcec;

    uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes

    // We need to hash 41 field elements when generating the NU challenge
    // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14)
    // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7)
    // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9)
    // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7)
    // table1_omega, table2_omega, table3_omega, table4_omega (4)
    uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20

    // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over
    // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4
    uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0

    uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P =
        0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
    uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68
    uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14

    error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual);
    error PUBLIC_INPUT_INVALID_BN128_G1_POINT();
    error PUBLIC_INPUT_GE_P();
    error MOD_EXP_FAILURE();
    error EC_SCALAR_MUL_FAILURE();
    error PROOF_FAILURE();

    function getVerificationKeyHash() public pure virtual returns (bytes32);

    function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual;

    /**
     * @notice Verify a Ultra Plonk proof
     * @param _proof - The serialized proof
     * @param _publicInputs - An array of the public inputs
     * @return True if proof is valid, reverts otherwise
     */
    function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) {
        loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC);

        uint256 requiredPublicInputCount;
        assembly {
            requiredPublicInputCount := mload(NUM_INPUTS_LOC)
        }
        if (requiredPublicInputCount != _publicInputs.length) {
            revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length);
        }

        assembly {
            let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order
            let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order

            /**
             * LOAD PROOF FROM CALLDATA
             */
            {
                let data_ptr := add(calldataload(0x04), 0x24)

                mstore(W1_Y_LOC, mod(calldataload(data_ptr), q))
                mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q))

                mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q))
                mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q))

                mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q))
                mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q))

                mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q))
                mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q))

                mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q))
                mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q))
                mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q))
                mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q))
                mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q))
                mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q))
                mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q))
                mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q))

                mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q))
                mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q))

                mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q))
                mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q))

                mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q))
                mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q))

                mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p))
                mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p))
                mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p))
                mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p))
                mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p))
                mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p))
                mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p))
                mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p))
                mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p))
                mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p))
                mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p))
                mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p))
                mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p))
                mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p))
                mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p))
                mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p))
                mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p))

                mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p))
                mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p))

                mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p))
                mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p))

                mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p))
                mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p))
                mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p))
                mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p))
                mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p))

                mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p))
                mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p))
                mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p))
                mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p))

                mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p))
                mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p))
                mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p))
                mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p))
                mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p))

                mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p))

                mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p))
                mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p))
                mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p))
                mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p))
                mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p))

                mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q))
                mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q))

                mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q))
                mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q))
            }

            /**
             * LOAD RECURSIVE PROOF INTO MEMORY
             */
            {
                if mload(CONTAINS_RECURSIVE_PROOF_LOC) {
                    let public_inputs_ptr := add(calldataload(0x24), 0x24)
                    let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr)

                    let x0 := calldataload(index_counter)
                    x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20))))
                    x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40))))
                    x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60))))
                    let y0 := calldataload(add(index_counter, 0x80))
                    y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0))))
                    y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0))))
                    y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0))))
                    let x1 := calldataload(add(index_counter, 0x100))
                    x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120))))
                    x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140))))
                    x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160))))
                    let y1 := calldataload(add(index_counter, 0x180))
                    y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0))))
                    y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0))))
                    y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0))))
                    mstore(RECURSIVE_P1_X_LOC, x0)
                    mstore(RECURSIVE_P1_Y_LOC, y0)
                    mstore(RECURSIVE_P2_X_LOC, x1)
                    mstore(RECURSIVE_P2_Y_LOC, y1)

                    // validate these are valid bn128 G1 points
                    if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) {
                        mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR)
                        revert(0x00, 0x04)
                    }
                }
            }

            {
                /**
                 * Generate initial challenge
                 */
                mstore(0x00, shl(224, mload(N_LOC)))
                mstore(0x04, shl(224, mload(NUM_INPUTS_LOC)))
                let challenge := keccak256(0x00, 0x08)

                /**
                 * Generate eta challenge
                 */
                mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge)
                // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs
                let public_inputs_start := add(calldataload(0x24), 0x24)
                // copy the public inputs over
                let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20)
                calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size)

                // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length)
                let w_start := add(calldataload(0x04), 0x24)
                calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH)

                // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0)
                let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH))

                challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size)
                {
                    let eta := mod(challenge, p)
                    mstore(C_ETA_LOC, eta)
                    mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p))
                    mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p))
                }

                /**
                 * Generate beta challenge
                 */
                mstore(0x00, challenge)
                mstore(0x20, mload(W4_Y_LOC))
                mstore(0x40, mload(W4_X_LOC))
                mstore(0x60, mload(S_Y_LOC))
                mstore(0x80, mload(S_X_LOC))
                challenge := keccak256(0x00, 0xa0)
                mstore(C_BETA_LOC, mod(challenge, p))

                /**
                 * Generate gamma challenge
                 */
                mstore(0x00, challenge)
                mstore8(0x20, 0x01)
                challenge := keccak256(0x00, 0x21)
                mstore(C_GAMMA_LOC, mod(challenge, p))

                /**
                 * Generate alpha challenge
                 */
                mstore(0x00, challenge)
                mstore(0x20, mload(Z_Y_LOC))
                mstore(0x40, mload(Z_X_LOC))
                mstore(0x60, mload(Z_LOOKUP_Y_LOC))
                mstore(0x80, mload(Z_LOOKUP_X_LOC))
                challenge := keccak256(0x00, 0xa0)
                mstore(C_ALPHA_LOC, mod(challenge, p))

                /**
                 * Compute and store some powers of alpha for future computations
                 */
                let alpha := mload(C_ALPHA_LOC)
                mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p))
                mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p))
                mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p))
                mstore(C_ALPHA_BASE_LOC, alpha)

                /**
                 * Generate zeta challenge
                 */
                mstore(0x00, challenge)
                mstore(0x20, mload(T1_Y_LOC))
                mstore(0x40, mload(T1_X_LOC))
                mstore(0x60, mload(T2_Y_LOC))
                mstore(0x80, mload(T2_X_LOC))
                mstore(0xa0, mload(T3_Y_LOC))
                mstore(0xc0, mload(T3_X_LOC))
                mstore(0xe0, mload(T4_Y_LOC))
                mstore(0x100, mload(T4_X_LOC))

                challenge := keccak256(0x00, 0x120)

                mstore(C_ZETA_LOC, mod(challenge, p))
                mstore(C_CURRENT_LOC, challenge)
            }

            /**
             * EVALUATE FIELD OPERATIONS
             */

            /**
             * COMPUTE PUBLIC INPUT DELTA
             * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ)
             */
            {
                let beta := mload(C_BETA_LOC) // β
                let gamma := mload(C_GAMMA_LOC) // γ
                let work_root := mload(OMEGA_LOC) // ω
                let numerator_value := 1
                let denominator_value := 1

                let p_clone := p // move p to the front of the stack
                let valid_inputs := true

                // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24])
                let public_inputs_ptr := add(calldataload(0x24), 0x24)

                // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes
                let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20))

                // root_1 = β * 0x05
                let root_1 := mulmod(beta, 0x05, p_clone) // k1.β
                // root_2 = β * 0x0c
                let root_2 := mulmod(beta, 0x0c, p_clone)
                // @note 0x05 + 0x07 == 0x0c == external coset generator

                for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } {
                    /**
                     * input = public_input[i]
                     * valid_inputs &= input < p
                     * temp = input + gamma
                     * numerator_value *= (β.σ(i) + wᵢ + γ)  // σ(i) = 0x05.ωⁱ
                     * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ
                     * root_1 *= ω
                     * root_2 *= ω
                     */

                    let input := calldataload(public_inputs_ptr)
                    valid_inputs := and(valid_inputs, lt(input, p_clone))
                    let temp := addmod(input, gamma, p_clone)

                    numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone)
                    denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone)

                    root_1 := mulmod(root_1, work_root, p_clone)
                    root_2 := mulmod(root_2, work_root, p_clone)
                }

                // Revert if not all public inputs are field elements (i.e. < p)
                if iszero(valid_inputs) {
                    mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR)
                    revert(0x00, 0x04)
                }

                mstore(DELTA_NUMERATOR_LOC, numerator_value)
                mstore(DELTA_DENOMINATOR_LOC, denominator_value)
            }

            /**
             * Compute Plookup delta factor [γ(1 + β)]^{n-k}
             * k = num roots cut out of Z_H = 4
             */
            {
                let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)
                let delta_numerator := delta_base
                {
                    let exponent := mload(N_LOC)
                    let count := 1
                    for {} lt(count, exponent) { count := add(count, count) } {
                        delta_numerator := mulmod(delta_numerator, delta_numerator, p)
                    }
                }
                mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator)

                let delta_denominator := mulmod(delta_base, delta_base, p)
                delta_denominator := mulmod(delta_denominator, delta_denominator, p)
                mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator)
            }
            /**
             * Compute lagrange poly and vanishing poly fractions
             */
            {
                /**
                 * vanishing_numerator = zeta
                 * ZETA_POW_N = zeta^n
                 * vanishing_numerator -= 1
                 * accumulating_root = omega_inverse
                 * work_root = p - accumulating_root
                 * domain_inverse = domain_inverse
                 * vanishing_denominator = zeta + work_root
                 * work_root *= accumulating_root
                 * vanishing_denominator *= (zeta + work_root)
                 * work_root *= accumulating_root
                 * vanishing_denominator *= (zeta + work_root)
                 * vanishing_denominator *= (zeta + (zeta + accumulating_root))
                 * work_root = omega
                 * lagrange_numerator = vanishing_numerator * domain_inverse
                 * l_start_denominator = zeta - 1
                 * accumulating_root = work_root^2
                 * l_end_denominator = accumulating_root^2 * work_root * zeta - 1
                 * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly
                 */

                let zeta := mload(C_ZETA_LOC)

                // compute zeta^n, where n is a power of 2
                let vanishing_numerator := zeta
                {
                    // pow_small
                    let exponent := mload(N_LOC)
                    let count := 1
                    for {} lt(count, exponent) { count := add(count, count) } {
                        vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p)
                    }
                }
                mstore(ZETA_POW_N_LOC, vanishing_numerator)
                vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p)

                let accumulating_root := mload(OMEGA_INVERSE_LOC)
                let work_root := sub(p, accumulating_root)
                let domain_inverse := mload(DOMAIN_INVERSE_LOC)

                let vanishing_denominator := addmod(zeta, work_root, p)
                work_root := mulmod(work_root, accumulating_root, p)
                vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)
                work_root := mulmod(work_root, accumulating_root, p)
                vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)
                vanishing_denominator :=
                    mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p)

                work_root := mload(OMEGA_LOC)

                let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p)
                let l_start_denominator := addmod(zeta, sub(p, 1), p)

                accumulating_root := mulmod(work_root, work_root, p)

                let l_end_denominator :=
                    addmod(
                        mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p
                    )

                /**
                 * Compute inversions using Montgomery's batch inversion trick
                 */
                let accumulator := mload(DELTA_DENOMINATOR_LOC)
                let t0 := accumulator
                accumulator := mulmod(accumulator, vanishing_denominator, p)
                let t1 := accumulator
                accumulator := mulmod(accumulator, vanishing_numerator, p)
                let t2 := accumulator
                accumulator := mulmod(accumulator, l_start_denominator, p)
                let t3 := accumulator
                accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)
                let t4 := accumulator
                {
                    mstore(0, 0x20)
                    mstore(0x20, 0x20)
                    mstore(0x40, 0x20)
                    mstore(0x60, mulmod(accumulator, l_end_denominator, p))
                    mstore(0x80, sub(p, 2))
                    mstore(0xa0, p)
                    if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) {
                        mstore(0x0, MOD_EXP_FAILURE_SELECTOR)
                        revert(0x00, 0x04)
                    }
                    accumulator := mload(0x00)
                }

                t4 := mulmod(accumulator, t4, p)
                accumulator := mulmod(accumulator, l_end_denominator, p)

                t3 := mulmod(accumulator, t3, p)
                accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)

                t2 := mulmod(accumulator, t2, p)
                accumulator := mulmod(accumulator, l_start_denominator, p)

                t1 := mulmod(accumulator, t1, p)
                accumulator := mulmod(accumulator, vanishing_numerator, p)

                t0 := mulmod(accumulator, t0, p)
                accumulator := mulmod(accumulator, vanishing_denominator, p)

                accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p)

                mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p))
                mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p))
                mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p))
                mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p))
                mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p))
                mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p))
            }

            /**
             * UltraPlonk Widget Ordering:
             *
             * 1. Permutation widget
             * 2. Plookup widget
             * 3. Arithmetic widget
             * 4. Fixed base widget (?)
             * 5. GenPermSort widget
             * 6. Elliptic widget
             * 7. Auxiliary widget
             */

            /**
             * COMPUTE PERMUTATION WIDGET EVALUATION
             */
            {
                let alpha := mload(C_ALPHA_LOC)
                let beta := mload(C_BETA_LOC)
                let gamma := mload(C_GAMMA_LOC)

                /**
                 * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2)
                 * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4)
                 * result = alpha_base * z_eval * t1 * t2
                 * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval)
                 * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval)
                 * result -= (alpha_base * z_omega_eval * t1 * t2)
                 */
                let t1 :=
                    mulmod(
                        add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)),
                        add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)),
                        p
                    )
                let t2 :=
                    mulmod(
                        add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)),
                        add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)),
                        p
                    )
                let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p)
                t1 :=
                    mulmod(
                        add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)),
                        add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)),
                        p
                    )
                t2 :=
                    mulmod(
                        add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)),
                        add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)),
                        p
                    )
                result :=
                    addmod(
                        result,
                        sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)),
                        p
                    )

                /**
                 * alpha_base *= alpha
                 * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI}))
                 * alpha_base *= alpha
                 * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1))
                 * alpha_Base *= alpha
                 */
                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
                result :=
                    addmod(
                        result,
                        mulmod(
                            mload(C_ALPHA_BASE_LOC),
                            mulmod(
                                mload(L_END_LOC),
                                addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p),
                                p
                            ),
                            p
                        ),
                        p
                    )
                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
                mstore(
                    PERMUTATION_IDENTITY,
                    addmod(
                        result,
                        mulmod(
                            mload(C_ALPHA_BASE_LOC),
                            mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p),
                            p
                        ),
                        p
                    )
                )
                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
            }

            /**
             * COMPUTE PLOOKUP WIDGET EVALUATION
             */
            {
                /**
                 * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³
                 * f = η.q3(z)
                 * f += (w3(z) + qc.w_3(zω))
                 * f *= η
                 * f += (w2(z) + qm.w2(zω))
                 * f *= η
                 * f += (w1(z) + q2.w1(zω))
                 */
                let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p)
                f :=
                    addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p)
                f := mulmod(f, mload(C_ETA_LOC), p)
                f :=
                    addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p)
                f := mulmod(f, mload(C_ETA_LOC), p)
                f :=
                    addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p)

                // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z)
                let t :=
                    addmod(
                        addmod(
                            addmod(
                                mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),
                                mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p),
                                p
                            ),
                            mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p),
                            p
                        ),
                        mload(TABLE1_EVAL_LOC),
                        p
                    )

                // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw)
                let t_omega :=
                    addmod(
                        addmod(
                            addmod(
                                mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),
                                mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p),
                                p
                            ),
                            mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p),
                            p
                        ),
                        mload(TABLE1_OMEGA_EVAL_LOC),
                        p
                    )

                /**
                 * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1)
                 * gamma_beta_constant = γ(β + 1)
                 * numerator = f * TABLE_TYPE_EVAL + gamma
                 * temp0 = t(z) + t(zω) * β + gamma_beta_constant
                 * numerator *= temp0
                 * numerator *= (β + 1)
                 * temp0 = alpha * l_1
                 * numerator += temp0
                 * numerator *= z_lookup(z)
                 * numerator -= temp0
                 */
                let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)
                let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p)
                let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p)
                numerator := mulmod(numerator, temp0, p)
                numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p)
                temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p)
                numerator := addmod(numerator, temp0, p)
                numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p)
                numerator := addmod(numerator, sub(p, temp0), p)

                /**
                 * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z)
                 * note: delta_factor = [γ(1 + β)]^{n-k}
                 * denominator = s(z) + βs(zω) + γ(β + 1)
                 * temp1 = α²L_end(z)
                 * denominator -= temp1
                 * denominator *= z_lookup(zω)
                 * denominator += temp1 * delta_factor
                 * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base
                 * alpha_base *= alpha^3
                 */
                let denominator :=
                    addmod(
                        addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p),
                        gamma_beta_constant,
                        p
                    )
                let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p)
                denominator := addmod(denominator, sub(p, temp1), p)
                denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p)
                denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p)

                mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p))

                // update alpha
                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))
            }

            /**
             * COMPUTE ARITHMETIC WIDGET EVALUATION
             */
            {
                /**
                 * The basic arithmetic gate identity in standard plonk is as follows.
                 * (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
                 * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below):
                 * 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 ) +
                 * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0
                 *
                 * This formula results in several cases depending on q_arith:
                 * 1. q_arith == 0: Arithmetic gate is completely disabled
                 *
                 * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation
                 * 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
                 *
                 * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is:
                 * (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
                 * It allows defining w_4 at next index (w_4_omega) in terms of current wire values
                 *
                 * 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
                 * the equation into two:
                 *
                 * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0
                 * and
                 * w_1 + w_4 - w_1_omega + q_m = 0  (we are reusing q_m here)
                 *
                 * 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).
                 * The equation can be split into two:
                 *
                 * (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
                 * and
                 * w_1 + w_4 - w_1_omega + q_m = 0
                 *
                 * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at
                 * 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
                 * product.
                 */

                let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p)
                let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p)
                let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p)
                let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p)

                // @todo - Add a explicit test that hits QARITH == 3
                // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2
                let w1w2qm :=
                    mulmod(
                        mulmod(
                            mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p),
                            addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p),
                            p
                        ),
                        NEGATIVE_INVERSE_OF_2_MODULO_P,
                        p
                    )

                // (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
                let identity :=
                    addmod(
                        mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p
                    )

                // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where:
                // w_1 + w_4 - w_1_omega + q_m = 0
                // we use this gate to save an addition gate when adding or subtracting non-native field elements
                // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m)
                let extra_small_addition_gate_identity :=
                    mulmod(
                        mload(C_ALPHA_LOC),
                        mulmod(
                            addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p),
                            addmod(
                                mload(QM_EVAL_LOC),
                                addmod(
                                    sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p
                                ),
                                p
                            ),
                            p
                        ),
                        p
                    )

                // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity
                // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires!
                // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity))
                mstore(
                    ARITHMETIC_IDENTITY,
                    mulmod(
                        mload(C_ALPHA_BASE_LOC),
                        mulmod(
                            mload(QARITH_EVAL_LOC),
                            addmod(
                                identity,
                                mulmod(
                                    addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p),
                                    addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p),
                                    p
                                ),
                                p
                            ),
                            p
                        ),
                        p
                    )
                )

                // update alpha
                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p))
            }

            /**
             * COMPUTE GENPERMSORT WIDGET EVALUATION
             */
            {
                /**
                 * D1 = (w2 - w1)
                 * D2 = (w3 - w2)
                 * D3 = (w4 - w3)
                 * D4 = (w1_omega - w4)
                 *
                 * α_a = alpha_base
                 * α_b = alpha_base * α
                 * α_c = alpha_base * α^2
                 * α_d = alpha_base * α^3
                 *
                 * range_accumulator = (
                 *   D1(D1 - 1)(D1 - 2)(D1 - 3).α_a +
                 *   D2(D2 - 1)(D2 - 2)(D2 - 3).α_b +
                 *   D3(D3 - 1)(D3 - 2)(D3 - 3).α_c +
                 *   D4(D4 - 1)(D4 - 2)(D4 - 3).α_d +
                 * ) . q_sort
                 */
                let minus_two := sub(p, 2)
                let minus_three := sub(p, 3)
                let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)
                let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)
                let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)
                let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)

                let range_accumulator :=
                    mulmod(
                        mulmod(
                            mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p),
                            addmod(d1, minus_three, p),
                            p
                        ),
                        mload(C_ALPHA_BASE_LOC),
                        p
                    )
                range_accumulator :=
                    addmod(
                        range_accumulator,
                        mulmod(
                            mulmod(
                                mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p),
                                addmod(d2, minus_three, p),
                                p
                            ),
                            mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),
                            p
                        ),
                        p
                    )
                range_accumulator :=
                    addmod(
                        range_accumulator,
                        mulmod(
                            mulmod(
                                mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p),
                                addmod(d3, minus_three, p),
                                p
                            ),
                            mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p),
                            p
                        ),
                        p
                    )
                range_accumulator :=
                    addmod(
                        range_accumulator,
                        mulmod(
                            mulmod(
                                mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p),
                                addmod(d4, minus_three, p),
                                p
                            ),
                            mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p),
                            p
                        ),
                        p
                    )
                range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p)

                mstore(SORT_IDENTITY, range_accumulator)

                // update alpha
                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))
            }

            /**
             * COMPUTE ELLIPTIC WIDGET EVALUATION
             */
            {
                /**
                 * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta
                 * endo_sqr_term = x_2^2
                 * endo_sqr_term *= (x_3 - x_1)
                 * endo_sqr_term *= q_beta^2
                 * leftovers = x_2^2
                 * leftovers *= x_2
                 * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget
                 * leftovers -= (y_2^2 + y_1^2)
                 * sign_term = y_2 * y_1
                 * sign_term += sign_term
                 * sign_term *= q_sign
                 */

                let endo_term :=
                    mulmod(
                        mulmod(
                            mulmod(sub(p, mload(X2_EVAL_LOC)), mload(X1_EVAL_LOC), p),
                            addmod(addmod(mload(X3_EVAL_LOC), mload(X3_EVAL_LOC), p), mload(X1_EVAL_LOC), p),
                            p
                        ),
                        mload(QBETA_LOC),
                        p
                    )

                let endo_sqr_term := mulmod(mload(X2_EVAL_LOC), mload(X2_EVAL_LOC), p)
                endo_sqr_term := mulmod(endo_sqr_term, addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), p)
                endo_sqr_term := mulmod(endo_sqr_term, mload(QBETA_SQR_LOC), p)

                let leftovers := mulmod(mload(X2_EVAL_LOC), mload(X2_EVAL_LOC), p)
                leftovers := mulmod(leftovers, mload(X2_EVAL_LOC), p)
                leftovers :=
                    addmod(
                        leftovers,
                        mulmod(
                            mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p),
                            addmod(mload(X3_EVAL_LOC), mload(X1_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                leftovers :=
                    addmod(
                        leftovers,
                        sub(
                            p,
                            addmod(
                                mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p),
                                mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p),
                                p
                            )
                        ),
                        p
                    )

                let sign_term := mulmod(mload(Y2_EVAL_LOC), mload(Y1_EVAL_LOC), p)
                sign_term := addmod(sign_term, sign_term, p)
                sign_term := mulmod(sign_term, mload(QSIGN_LOC), p)

                /**
                 * x_identity = endo_term + endo_sqr_term + sign_term + leftovers
                 * x_identity *= alpha_base
                 * endo_term = (x_2 * q_beta) * (y_3 + y_1)
                 * sign_term = -((y2 * q_sign) * (x_1 + x_3))
                 * leftovers = - x1 * (y_3 + y_1) + y_1 * (x_1 - x_3)
                 * y_identity = (endo_term + sign_term + leftovers) * (alpha_base * α)
                 */

                let x_identity := addmod(addmod(endo_term, endo_sqr_term, p), addmod(sign_term, leftovers, p), p)
                x_identity := mulmod(x_identity, mload(C_ALPHA_BASE_LOC), p)
                endo_term :=
                    mulmod(
                        mulmod(mload(X2_EVAL_LOC), mload(QBETA_LOC), p),
                        addmod(mload(Y3_EVAL_LOC), mload(Y1_EVAL_LOC), p),
                        p
                    )
                sign_term :=
                    sub(
                        p,
                        mulmod(
                            mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p),
                            addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p),
                            p
                        )
                    )
                leftovers :=
                    addmod(
                        sub(p, mulmod(mload(X1_EVAL_LOC), addmod(mload(Y3_EVAL_LOC), mload(Y1_EVAL_LOC), p), p)),
                        mulmod(mload(Y1_EVAL_LOC), addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p),
                        p
                    )
                let y_identity :=
                    mulmod(
                        addmod(addmod(endo_term, sign_term, p), leftovers, p),
                        mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),
                        p
                    )

                // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL
                mstore(ELLIPTIC_IDENTITY, mulmod(addmod(x_identity, y_identity, p), mload(QELLIPTIC_EVAL_LOC), p))

                // update alpha
                // The paper says to use ALPHA^2, we use ALPHA^4 this is a small oversight in the prover protocol
                mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))
            }

            /**
             * COMPUTE AUXILIARY WIDGET EVALUATION
             */
            {
                {
                    /**
                     * Non native field arithmetic gate 2
                     *             _                                                                               _
                     *            /   _                   _                               _       14                \
                     * 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   |
                     *            \_                                                                               _/
                     *
                     * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2
                     * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega
                     * non_native_field_gate_2 = non_native_field_gate_2 * limb_size
                     * non_native_field_gate_2 -= w_4_omega
                     * non_native_field_gate_2 += limb_subproduct
                     * non_native_field_gate_2 *= q_4
                     * limb_subproduct *= limb_size
                     * limb_subproduct += w_1_omega * w_2_omega
                     * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3
                     * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m
                     * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2
                     */

                    let limb_subproduct :=
                        addmod(
                            mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p),
                            mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p),
                            p
                        )

                    let non_native_field_gate_2 :=
                        addmod(
                            addmod(
                                mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p),
                                mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p),
                                p
                            ),
                            sub(p, mload(W3_OMEGA_EVAL_LOC)),
                            p
                        )
                    non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p)
                    non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)
                    non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p)
                    non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p)
                    limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p)
                    limb_subproduct :=
                        addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p)
                    let non_native_field_gate_1 :=
                        mulmod(
                            addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p),
                            mload(Q3_EVAL_LOC),
                            p
                        )
                    let non_native_field_gate_3 :=
                        mulmod(
                            addmod(
                                addmod(limb_subproduct, mload(W4_EVAL_LOC), p),
                                sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)),
                                p
                            ),
                            mload(QM_EVAL_LOC),
                            p
                        )
                    let non_native_field_identity :=
                        mulmod(
                            addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p),
                            mload(Q2_EVAL_LOC),
                            p
                        )

                    mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity)
                }

                {
                    /**
                     * limb_accumulator_1 = w_2_omega;
                     * limb_accumulator_1 *= SUBLIMB_SHIFT;
                     * limb_accumulator_1 += w_1_omega;
                     * limb_accumulator_1 *= SUBLIMB_SHIFT;
                     * limb_accumulator_1 += w_3;
                     * limb_accumulator_1 *= SUBLIMB_SHIFT;
                     * limb_accumulator_1 += w_2;
                     * limb_accumulator_1 *= SUBLIMB_SHIFT;
                     * limb_accumulator_1 += w_1;
                     * limb_accumulator_1 -= w_4;
                     * limb_accumulator_1 *= q_4;
                     */
                    let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)
                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p)
                    limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p)
                    limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p)
                    limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
                    limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p)
                    limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p)
                    limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p)

                    /**
                     * limb_accumulator_2 = w_3_omega;
                     * limb_accumulator_2 *= SUBLIMB_SHIFT;
                     * limb_accumulator_2 += w_2_omega;
                     * limb_accumulator_2 *= SUBLIMB_SHIFT;
                     * limb_accumulator_2 += w_1_omega;
                     * limb_accumulator_2 *= SUBLIMB_SHIFT;
                     * limb_accumulator_2 += w_4;
                     * limb_accumulator_2 *= SUBLIMB_SHIFT;
                     * limb_accumulator_2 += w_3;
                     * limb_accumulator_2 -= w_4_omega;
                     * limb_accumulator_2 *= q_m;
                     */
                    let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)
                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p)
                    limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p)
                    limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p)
                    limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
                    limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p)
                    limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)
                    limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p)

                    mstore(
                        AUX_LIMB_ACCUMULATOR_EVALUATION,
                        mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p)
                    )
                }

                {
                    /**
                     * memory_record_check = w_3;
                     * memory_record_check *= eta;
                     * memory_record_check += w_2;
                     * memory_record_check *= eta;
                     * memory_record_check += w_1;
                     * memory_record_check *= eta;
                     * memory_record_check += q_c;
                     *
                     * partial_record_check = memory_record_check;
                     *
                     * memory_record_check -= w_4;
                     */

                    let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p)
                    memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p)
                    memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)
                    memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p)
                    memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)
                    memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p)

                    let partial_record_check := memory_record_check
                    memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p)

                    mstore(AUX_MEMORY_EVALUATION, memory_record_check)

                    // index_delta = w_1_omega - w_1
                    let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)
                    // record_delta = w_4_omega - w_4
                    let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)
                    // index_is_monotonically_increasing = index_delta * (index_delta - 1)
                    let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p)

                    // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta)
                    let adjacent_values_match_if_adjacent_indices_match :=
                        mulmod(record_delta, addmod(1, sub(p, index_delta), p), p)

                    // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check
                    mstore(
                        AUX_ROM_CONSISTENCY_EVALUATION,
                        addmod(
                            mulmod(
                                addmod(
                                    mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p),
                                    index_is_monotonically_increasing,
                                    p
                                ),
                                mload(C_ALPHA_LOC),
                                p
                            ),
                            memory_record_check,
                            p
                        )
                    )

                    {
                        /**
                         * next_gate_access_type = w_3_omega;
                         * next_gate_access_type *= eta;
                         * next_gate_access_type += w_2_omega;
                         * next_gate_access_type *= eta;
                         * next_gate_access_type += w_1_omega;
                         * next_gate_access_type *= eta;
                         * next_gate_access_type = w_4_omega - next_gate_access_type;
                         */
                        let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p)
                        next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p)
                        next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)
                        next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p)
                        next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)
                        next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p)

                        // value_delta = w_3_omega - w_3
                        let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)
                        //  adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type);

                        let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation :=
                            mulmod(
                                addmod(1, sub(p, index_delta), p),
                                mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p),
                                p
                            )

                        // AUX_RAM_CONSISTENCY_EVALUATION

                        /**
                         * access_type = w_4 - partial_record_check
                         * access_check = access_type^2 - access_type
                         * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type
                         * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation;
                         * RAM_consistency_check_identity *= alpha;
                         * RAM_consistency_check_identity += index_is_monotonically_increasing;
                         * RAM_consistency_check_identity *= alpha;
                         * RAM_consistency_check_identity += next_gate_access_type_is_boolean;
                         * RAM_consistency_check_identity *= alpha;
                         * RAM_consistency_check_identity += access_check;
                         */

                        let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p)
                        let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p)
                        let next_gate_access_type_is_boolean :=
                            mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p)
                        let RAM_cci :=
                            mulmod(
                                adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation,
                                mload(C_ALPHA_LOC),
                                p
                            )
                        RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p)
                        RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)
                        RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p)
                        RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)
                        RAM_cci := addmod(RAM_cci, access_check, p)

                        mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci)
                    }

                    {
                        // timestamp_delta = w_2_omega - w_2
                        let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)

                        // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3
                        let RAM_timestamp_check_identity :=
                            addmod(
                                mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p
                            )

                        /**
                         * memory_identity = ROM_consistency_check_identity * q_2;
                         * memory_identity += RAM_timestamp_check_identity * q_4;
                         * memory_identity += memory_record_check * q_m;
                         * memory_identity *= q_1;
                         * memory_identity += (RAM_consistency_check_identity * q_arith);
                         *
                         * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity;
                         * auxiliary_identity *= q_aux;
                         * auxiliary_identity *= alpha_base;
                         */
                        let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p)
                        memory_identity :=
                            addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p)
                        memory_identity :=
                            addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p)
                        memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p)
                        memory_identity :=
                            addmod(
                                memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p
                            )

                        let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p)
                        auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p)
                        auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p)
                        auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p)

                        mstore(AUX_IDENTITY, auxiliary_identity)

                        // update alpha
                        mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))
                    }
                }
            }

            {
                /**
                 * quotient = ARITHMETIC_IDENTITY
                 * quotient += PERMUTATION_IDENTITY
                 * quotient += PLOOKUP_IDENTITY
                 * quotient += SORT_IDENTITY
                 * quotient += ELLIPTIC_IDENTITY
                 * quotient += AUX_IDENTITY
                 * quotient *= ZERO_POLY_INVERSE
                 */
                mstore(
                    QUOTIENT_EVAL_LOC,
                    mulmod(
                        addmod(
                            addmod(
                                addmod(
                                    addmod(
                                        addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p),
                                        mload(ARITHMETIC_IDENTITY),
                                        p
                                    ),
                                    mload(SORT_IDENTITY),
                                    p
                                ),
                                mload(ELLIPTIC_IDENTITY),
                                p
                            ),
                            mload(AUX_IDENTITY),
                            p
                        ),
                        mload(ZERO_POLY_INVERSE_LOC),
                        p
                    )
                )
            }

            /**
             * GENERATE NU AND SEPARATOR CHALLENGES
             */
            {
                let current_challenge := mload(C_CURRENT_LOC)
                // get a calldata pointer that points to the start of the data we want to copy
                let calldata_ptr := add(calldataload(0x04), 0x24)

                calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH)

                mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge)
                mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC))
                calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH)

                // hash length = (0x20 + num field elements), we include the previous challenge in the hash
                let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40))

                mstore(C_V0_LOC, mod(challenge, p))
                // We need THIRTY-ONE independent nu challenges!
                mstore(0x00, challenge)
                mstore8(0x20, 0x01)
                mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x02)
                mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x03)
                mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x04)
                mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x05)
                mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x06)
                mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x07)
                mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x08)
                mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x09)
                mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x0a)
                mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x0b)
                mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x0c)
                mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x0d)
                mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x0e)
                mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x0f)
                mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x10)
                mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x11)
                mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x12)
                mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x13)
                mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x14)
                mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x15)
                mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x16)
                mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x17)
                mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x18)
                mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x19)
                mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x1a)
                mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x1b)
                mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x1c)
                mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p))
                mstore8(0x20, 0x1d)
                mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p))

                // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change?
                mstore8(0x20, 0x1d)
                challenge := keccak256(0x00, 0x21)
                mstore(C_V30_LOC, mod(challenge, p))

                // separator
                mstore(0x00, challenge)
                mstore(0x20, mload(PI_Z_Y_LOC))
                mstore(0x40, mload(PI_Z_X_LOC))
                mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))
                mstore(0x80, mload(PI_Z_OMEGA_X_LOC))

                mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p))
            }

            let success := 0
            // VALIDATE T1
            {
                let x := mload(T1_X_LOC)
                let y := mload(T1_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))
                mstore(ACCUMULATOR_X_LOC, x)
                mstore(add(ACCUMULATOR_X_LOC, 0x20), y)
            }
            // VALIDATE T2
            {
                let x := mload(T2_X_LOC) // 0x1400
                let y := mload(T2_Y_LOC) // 0x1420
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(ZETA_POW_N_LOC))
            // accumulator_2 = [T2].zeta^n
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = [T1] + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE T3
            {
                let x := mload(T3_X_LOC)
                let y := mload(T3_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p))
            // accumulator_2 = [T3].zeta^{2n}
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE T4
            {
                let x := mload(T4_X_LOC)
                let y := mload(T4_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p))
            // accumulator_2 = [T4].zeta^{3n}
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE W1
            {
                let x := mload(W1_X_LOC)
                let y := mload(W1_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p))
            // accumulator_2 = v0.(u + 1).[W1]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE W2
            {
                let x := mload(W2_X_LOC)
                let y := mload(W2_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p))
            // accumulator_2 = v1.(u + 1).[W2]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE W3
            {
                let x := mload(W3_X_LOC)
                let y := mload(W3_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p))
            // accumulator_2 = v2.(u + 1).[W3]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE W4
            {
                let x := mload(W4_X_LOC)
                let y := mload(W4_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p))
            // accumulator_2 = v3.(u + 1).[W4]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE S
            {
                let x := mload(S_X_LOC)
                let y := mload(S_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p))
            // accumulator_2 = v4.(u + 1).[S]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE Z
            {
                let x := mload(Z_X_LOC)
                let y := mload(Z_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p))
            // accumulator_2 = v5.(u + 1).[Z]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE Z_LOOKUP
            {
                let x := mload(Z_LOOKUP_X_LOC)
                let y := mload(Z_LOOKUP_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p))
            // accumulator_2 = v6.(u + 1).[Z_LOOKUP]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE Q1
            {
                let x := mload(Q1_X_LOC)
                let y := mload(Q1_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V7_LOC))
            // accumulator_2 = v7.[Q1]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE Q2
            {
                let x := mload(Q2_X_LOC)
                let y := mload(Q2_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V8_LOC))
            // accumulator_2 = v8.[Q2]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE Q3
            {
                let x := mload(Q3_X_LOC)
                let y := mload(Q3_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V9_LOC))
            // accumulator_2 = v9.[Q3]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE Q4
            {
                let x := mload(Q4_X_LOC)
                let y := mload(Q4_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V10_LOC))
            // accumulator_2 = v10.[Q4]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE QM
            {
                let x := mload(QM_X_LOC)
                let y := mload(QM_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V11_LOC))
            // accumulator_2 = v11.[Q;]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE QC
            {
                let x := mload(QC_X_LOC)
                let y := mload(QC_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V12_LOC))
            // accumulator_2 = v12.[QC]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE QARITH
            {
                let x := mload(QARITH_X_LOC)
                let y := mload(QARITH_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V13_LOC))
            // accumulator_2 = v13.[QARITH]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE QSORT
            {
                let x := mload(QSORT_X_LOC)
                let y := mload(QSORT_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V14_LOC))
            // accumulator_2 = v14.[QSORT]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE QELLIPTIC
            {
                let x := mload(QELLIPTIC_X_LOC)
                let y := mload(QELLIPTIC_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V15_LOC))
            // accumulator_2 = v15.[QELLIPTIC]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE QAUX
            {
                let x := mload(QAUX_X_LOC)
                let y := mload(QAUX_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V16_LOC))
            // accumulator_2 = v15.[Q_AUX]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE SIGMA1
            {
                let x := mload(SIGMA1_X_LOC)
                let y := mload(SIGMA1_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V17_LOC))
            // accumulator_2 = v17.[sigma1]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE SIGMA2
            {
                let x := mload(SIGMA2_X_LOC)
                let y := mload(SIGMA2_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V18_LOC))
            // accumulator_2 = v18.[sigma2]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE SIGMA3
            {
                let x := mload(SIGMA3_X_LOC)
                let y := mload(SIGMA3_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V19_LOC))
            // accumulator_2 = v19.[sigma3]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE SIGMA4
            {
                let x := mload(SIGMA4_X_LOC)
                let y := mload(SIGMA4_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V20_LOC))
            // accumulator_2 = v20.[sigma4]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE TABLE1
            {
                let x := mload(TABLE1_X_LOC)
                let y := mload(TABLE1_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p))
            // accumulator_2 = u.[table1]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE TABLE2
            {
                let x := mload(TABLE2_X_LOC)
                let y := mload(TABLE2_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p))
            // accumulator_2 = u.[table2]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE TABLE3
            {
                let x := mload(TABLE3_X_LOC)
                let y := mload(TABLE3_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p))
            // accumulator_2 = u.[table3]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE TABLE4
            {
                let x := mload(TABLE4_X_LOC)
                let y := mload(TABLE4_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p))
            // accumulator_2 = u.[table4]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE TABLE_TYPE
            {
                let x := mload(TABLE_TYPE_X_LOC)
                let y := mload(TABLE_TYPE_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V25_LOC))
            // accumulator_2 = v25.[TableType]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE ID1
            {
                let x := mload(ID1_X_LOC)
                let y := mload(ID1_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V26_LOC))
            // accumulator_2 = v26.[ID1]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE ID2
            {
                let x := mload(ID2_X_LOC)
                let y := mload(ID2_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V27_LOC))
            // accumulator_2 = v27.[ID2]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE ID3
            {
                let x := mload(ID3_X_LOC)
                let y := mload(ID3_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V28_LOC))
            // accumulator_2 = v28.[ID3]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            // VALIDATE ID4
            {
                let x := mload(ID4_X_LOC)
                let y := mload(ID4_Y_LOC)
                let xx := mulmod(x, x, q)
                // validate on curve
                success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                mstore(0x00, x)
                mstore(0x20, y)
            }
            mstore(0x40, mload(C_V29_LOC))
            // accumulator_2 = v29.[ID4]
            success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
            // accumulator = accumulator + accumulator_2
            success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

            /**
             * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER
             */
            {
                /**
                 * batch_evaluation = v0 * (w_1_omega * u + w_1_eval)
                 * batch_evaluation += v1 * (w_2_omega * u + w_2_eval)
                 * batch_evaluation += v2 * (w_3_omega * u + w_3_eval)
                 * batch_evaluation += v3 * (w_4_omega * u + w_4_eval)
                 * batch_evaluation += v4 * (s_omega_eval * u + s_eval)
                 * batch_evaluation += v5 * (z_omega_eval * u + z_eval)
                 * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval)
                 */
                let batch_evaluation :=
                    mulmod(
                        mload(C_V0_LOC),
                        addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V1_LOC),
                            addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V2_LOC),
                            addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V3_LOC),
                            addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V4_LOC),
                            addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V5_LOC),
                            addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V6_LOC),
                            addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p),
                            p
                        ),
                        p
                    )

                /**
                 * batch_evaluation += v7 * Q1_EVAL
                 * batch_evaluation += v8 * Q2_EVAL
                 * batch_evaluation += v9 * Q3_EVAL
                 * batch_evaluation += v10 * Q4_EVAL
                 * batch_evaluation += v11 * QM_EVAL
                 * batch_evaluation += v12 * QC_EVAL
                 * batch_evaluation += v13 * QARITH_EVAL
                 * batch_evaluation += v14 * QSORT_EVAL_LOC
                 * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC
                 * batch_evaluation += v16 * QAUX_EVAL_LOC
                 * batch_evaluation += v17 * SIGMA1_EVAL_LOC
                 * batch_evaluation += v18 * SIGMA2_EVAL_LOC
                 * batch_evaluation += v19 * SIGMA3_EVAL_LOC
                 * batch_evaluation += v20 * SIGMA4_EVAL_LOC
                 */
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p)

                /**
                 * batch_evaluation += v21 * (table1(zw) * u + table1(z))
                 * batch_evaluation += v22 * (table2(zw) * u + table2(z))
                 * batch_evaluation += v23 * (table3(zw) * u + table3(z))
                 * batch_evaluation += v24 * (table4(zw) * u + table4(z))
                 * batch_evaluation += v25 * table_type_eval
                 * batch_evaluation += v26 * id1_eval
                 * batch_evaluation += v27 * id2_eval
                 * batch_evaluation += v28 * id3_eval
                 * batch_evaluation += v29 * id4_eval
                 * batch_evaluation += quotient_eval
                 */
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V21_LOC),
                            addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V22_LOC),
                            addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V23_LOC),
                            addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation :=
                    addmod(
                        batch_evaluation,
                        mulmod(
                            mload(C_V24_LOC),
                            addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p),
                            p
                        ),
                        p
                    )
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p)
                batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p)

                mstore(0x00, 0x01) // [1].x
                mstore(0x20, 0x02) // [1].y
                mstore(0x40, sub(p, batch_evaluation))
                // accumulator_2 = -[1].(batch_evaluation)
                success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
                // accumulator = accumulator + accumulator_2
                success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

                mstore(OPENING_COMMITMENT_SUCCESS_FLAG, success)
            }

            /**
             * PERFORM PAIRING PREAMBLE
             */
            {
                let u := mload(C_U_LOC)
                let zeta := mload(C_ZETA_LOC)
                // VALIDATE PI_Z
                {
                    let x := mload(PI_Z_X_LOC)
                    let y := mload(PI_Z_Y_LOC)
                    let xx := mulmod(x, x, q)
                    // validate on curve
                    success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))
                    mstore(0x00, x)
                    mstore(0x20, y)
                }
                // compute zeta.[PI_Z] and add into accumulator
                mstore(0x40, zeta)
                success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
                // accumulator = accumulator + accumulator_2
                success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))

                // VALIDATE PI_Z_OMEGA
                {
                    let x := mload(PI_Z_OMEGA_X_LOC)
                    let y := mload(PI_Z_OMEGA_Y_LOC)
                    let xx := mulmod(x, x, q)
                    // validate on curve
                    success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                    mstore(0x00, x)
                    mstore(0x20, y)
                }
                mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p))
                // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA]
                success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
                // PAIRING_RHS = accumulator + accumulator_2
                success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40))

                mstore(0x00, mload(PI_Z_X_LOC))
                mstore(0x20, mload(PI_Z_Y_LOC))
                mstore(0x40, mload(PI_Z_OMEGA_X_LOC))
                mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))
                mstore(0x80, u)
                success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40))
                // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u
                success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))
                // negate lhs y-coordinate
                mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC)))

                if mload(CONTAINS_RECURSIVE_PROOF_LOC) {
                    // VALIDATE RECURSIVE P1
                    {
                        let x := mload(RECURSIVE_P1_X_LOC)
                        let y := mload(RECURSIVE_P1_Y_LOC)
                        let xx := mulmod(x, x, q)
                        // validate on curve
                        success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                        mstore(0x00, x)
                        mstore(0x20, y)
                    }

                    // compute u.u.[recursive_p1] and write into 0x60
                    mstore(0x40, mulmod(u, u, p))
                    success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40))
                    // VALIDATE RECURSIVE P2
                    {
                        let x := mload(RECURSIVE_P2_X_LOC)
                        let y := mload(RECURSIVE_P2_Y_LOC)
                        let xx := mulmod(x, x, q)
                        // validate on curve
                        success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
                        mstore(0x00, x)
                        mstore(0x20, y)
                    }
                    // compute u.u.[recursive_p2] and write into 0x00
                    // 0x40 still contains u*u
                    success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40))

                    // compute u.u.[recursiveP1] + rhs and write into rhs
                    mstore(0xa0, mload(PAIRING_RHS_X_LOC))
                    mstore(0xc0, mload(PAIRING_RHS_Y_LOC))
                    success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40))

                    // compute u.u.[recursiveP2] + lhs and write into lhs
                    mstore(0x40, mload(PAIRING_LHS_X_LOC))
                    mstore(0x60, mload(PAIRING_LHS_Y_LOC))
                    success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))
                }

                if iszero(success) {
                    mstore(0x0, EC_SCALAR_MUL_FAILURE_SELECTOR)
                    revert(0x00, 0x04)
                }
                mstore(PAIRING_PREAMBLE_SUCCESS_FLAG, success)
            }

            /**
             * PERFORM PAIRING
             */
            {
                // rhs paired with [1]_2
                // lhs paired with [x]_2

                mstore(0x00, mload(PAIRING_RHS_X_LOC))
                mstore(0x20, mload(PAIRING_RHS_Y_LOC))
                mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2
                mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed)
                mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b)
                mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa)

                mstore(0xc0, mload(PAIRING_LHS_X_LOC))
                mstore(0xe0, mload(PAIRING_LHS_Y_LOC))
                mstore(0x100, mload(G2X_X0_LOC))
                mstore(0x120, mload(G2X_X1_LOC))
                mstore(0x140, mload(G2X_Y0_LOC))
                mstore(0x160, mload(G2X_Y1_LOC))

                success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20)
                mstore(PAIRING_SUCCESS_FLAG, success)
                mstore(RESULT_FLAG, mload(0x00))
            }
            if iszero(
                and(
                    and(and(mload(PAIRING_SUCCESS_FLAG), mload(RESULT_FLAG)), mload(PAIRING_PREAMBLE_SUCCESS_FLAG)),
                    mload(OPENING_COMMITMENT_SUCCESS_FLAG)
                )
            ) {
                mstore(0x0, PROOF_FAILURE_SELECTOR)
                revert(0x00, 0x04)
            }
            {
                mstore(0x00, 0x01)
                return(0x00, 0x20) // Proof succeeded!
            }
        }
    }
}

contract UltraVerifier is BaseUltraVerifier {
    function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) {
        return UltraVerificationKey.verificationKeyHash();
    }

    function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) {
        UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc);
    }
}

Contract ABI

[{"inputs":[],"name":"EC_SCALAR_MUL_FAILURE","type":"error"},{"inputs":[],"name":"MOD_EXP_FAILURE","type":"error"},{"inputs":[],"name":"PROOF_FAILURE","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"PUBLIC_INPUT_COUNT_INVALID","type":"error"},{"inputs":[],"name":"PUBLIC_INPUT_GE_P","type":"error"},{"inputs":[],"name":"PUBLIC_INPUT_INVALID_BN128_G1_POINT","type":"error"},{"inputs":[],"name":"getVerificationKeyHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_proof","type":"bytes"},{"internalType":"bytes32[]","name":"_publicInputs","type":"bytes32[]"}],"name":"verify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50612d05806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461006e575b600080fd5b6040517fd11f99e40c55d0ef202afc9d6497a56340bb8a86b5ceb40f13c6d96d72d9fcca81526020015b60405180910390f35b61008161007c366004612c0a565b610091565b6040519015158152602001610065565b620200006103805260376103a0527f1bf82deba7d74902c3708cc6e70e61f30512eca95655210e276e5858ce8f58e56103c0527f30643640b9f82f90e83b698e5ea6179c7c05542e859533b48b9953a2f53608016103e0527f245285cdf6c55535c4c72ecc89b3806ab342cd6e01bbb82b0c5c0113cba4a211610400527f1b565aa264e9d606df12185b82e6576a58d4513d864ed651927e961e461dcc86610420527f272dc56c0559a6089e4c3b48edd6c4c80fa911f5c041cbe3af06f7614bbbb43a610440527f18e69137e65a9875f4ee14c4880f5d0506defdade9186ba227b1e46a7652c0ed610460527f1f7131f4d583fc283d61e1c1053c70ab3ae7afbb4b2b4b95fbbd1c1430dabc16610480527f2a787bbadc7214d359b0feeabb1fdd0722801bdb1383aceeac392d3b8e4c40656104a0527f1735f148bd3f021f7e5401fb512f967181d442b239dd607d741d9924d9753ed46104c0527f19da04c1072f90dc7bdc09fc92b41b0f89d97347b8021ddd54fb8fba967b23316104e0527f031ad7e57c0c7113b369040cbfc3dd8de50d32e976e183e1c933096bef9c6a7f610500527f0f571b6887f7af84ec8c11b3d00705d218fd60433cf7f407ff610bc9e874017d610520527f2dddf1ada8a8d49f4437fbb93af9165e4af883c41a7ade0c4d714e11242703c5610540527f21ad6325b7bc4c8223416ba9d17ccecc6d5667cfe176791a5f02c6df49c9af5b610560527f245bf8a517b30344ac2e9c1387e2ffbfcb15877ccf9dc167f0c810d6cf763317610580527f2f200231a08e7beeffde231718ab0ab8dc9dbe96e0929a07d7adb342d012978a6105a0527f23ac6d2f41b030d51bbc19ccfb4648d70e875206a22124faddfa4d3fbd1352786105c0527f2d24acb1262a55fcef579f9249ddae57c5a20a84ec61d37fb845599824bb317a6105e0527f2e438eb058a779a5ad4135fd7e14d1145a038cc260c09cc8622bc19b90cf5dbe610600527f288504c94c6277a8b5004fc5dde949f0ce8c895e56d52e62d4f1c9175b19b45e610620527f1414af76247139fa9e8fef8b393a3e03227ee3a6fedb1e55f5db82cb2352782a610640527f2c7895a68d2fab5b2bce4d7703daebf9011e63d675bc6898c7f06087d6d83d99610660527f18b742204f0348b5c1b38c8a1a3698f99696f77b0739572ed32f5ff735587526610680527f180c4419454e91a4cf890444c937e108ffce7e3f88d86fcff3753c38b0a23f666106a0527f0a6ff425e08220154841bf2ca49c216137315a40781c7df12ce13543ab59a4cd6106c0527f1ae3a99295d617eecf7abde22269ebf78cc7060000dcb08a8c37d00f9e630a9b6106e0527f2132af6633a1cc574d02e157dad9a69b22c1f5caa5bbcc22db5a95132e3bf076610700527f2e79886ca28210ee429fd38d3727f549f2f91e1dee91e5f875f8b588d367b527610720527ec465601b3d03dffc34f62e0f11de17542c4a745b7a878ce754c1f4ad82bfae610740527e60c9633269601f6fcb01b6d26d46ee93055f807a2a1c9e7c33d186f04f65f8610760527f1f085b2095ee26145e167f353ef9a02dde005b3ba11bf60add10bdd9c00e7643610780527f0748759c43af1624acf605b6a23ebba01173cd346730c934d5fb7edd48413f946107a0527f2c8d2b9623692ab46021a60209f7148458ecb2ccdbbd766251f463ca7c53489a6107c0527f1aefa543256fc4b49dc193383f0156f7c331a2b89d0a0b5938a2fe2abe136d196107e0527f058ea36a362c899e3304278eca9a52fa74b07588d35cc5583278237cbbb53d68610800527f2afc5a5c85ca7b8fdac8a2b082096621e184e5a00a5cf1d481e28ad8071a691a610820527f14864cbfc194228094a325c4abf8260dbdca65e4883fce1425ec2933843b6737610840527f1489390b9b42c540c675cfea8acb88ceebe8c678f21ee8e8bee12af884fc1c3d610860527f2e6f974274a8b0d7c22721399c87384f68404226f622f0e50f9182fe4a9c7af3610880527f1bd608ba7bca523c9564c26bb23e27553fa0a0071e77a4123590e98b57860f096108a0527f1106ffa0e5b65066a1e6f54849a38c0fa40cd0f86edfb8c53de73175aa1a0aaa6108c0527f04caf81aa2aa53dd6a58b56d058005810cf634fbef2fd7945ee29aaa8744414a6108e0527f0acafc98985553ff731f444d22822ca2054385216d1e9f003b84868dfef67f5a610900527f059fc7ed336de83aac1273db4f51760b61cba1a42f3495738653ab46370dde76610920527f2d6688fcab60e29a560b4e4e03e0cc0d9e43dfb8d5b192e722d72a0e3adafdaf610940527f02bbd2a1bd7674a5b4e764db185aa85418f61b44c800329a3c43893f07a3c35a610960527f2e68f5b79c21422d3a849acc310202e3507f9ffd78d24d930c2b764393cd3e8f610980527f018e8379fcfaa214c9b07a4d500b14c6b03f2e218423a61c59d6e569a6a77a6e6109a05260006109c08190526109e08190527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1610a00527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0610a20527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4610a40527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55610a60527f244cf010c43ca87237d8b00bf9dd50c4c01c7f086bd4e8c920e75251d96f0d22613400526103a05182811461088657604051637667dc9b60e01b8152600481018290526024810184905260440160405180910390fd5b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd477f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016024600435018281350661122052826020820135066112005282604082013506611260528260608201350661124052826080820135066112a0528260a082013506611280528260c0820135066112e0528260e0820135066112c05282610100820135066113205282610120820135066113005282610140820135066113605282610160820135066113405282610180820135066113a052826101a08201350661138052826101c0820135066113e052826101e0820135066113c05282610200820135066114205282610220820135066114005282610240820135066114605282610260820135066114405282610280820135066114a052826102a08201350661148052816102c08201350661160052816102e0820135066116205281610300820135066116405281610320820135066116605281610340820135066116805281610360820135066116a05281610380820135066116c052816103a0820135066116e052816103c08201350661170052816103e0820135066117205281610400820135066117405281610420820135066117605281610440820135066117805281610460820135066117a05281610480820135066117c052816104a0820135066117e052816104c08201350661180052816104e0820135066119605281610500820135066119805281610520820135066119a05281610540820135066119c052816105608201350661184052816105808201350661186052816105a08201350661188052816105c0820135066118a052816105e0820135066118c05281610600820135066118e05281610620820135066119005281610640820135066119205281610660820135066119405281610680820135066119e052816106a08201350661200052816106c08201350661202052816106e0820135066120405281610700820135066120605281610720820135066120805281610740820135066120a05281610760820135066120c05281610780820135066120e052816107a08201350661210052816107c08201350661212052826107e08201350661232052826108008201350661230052826108208201350661236052826108408201350661234052506109c05115610ce8576024803501806109e05160051b0190508035602082013560441b81019050604082013560881b81019050606082013560cc1b81019050608082013560a083013560441b8101905060c083013560881b8101905060e083013560cc1b8101905061010083013561012084013560441b8101905061014084013560881b8101905061016084013560cc1b810190506101808401356101a085013560441b810190506101c085013560881b810190506101e085013560cc1b810190508361350052826135205281613540528061356052868110878410168783108886101616610ce2576375d4fa5360e11b60005260046000fd5b50505050505b6103805160e01b6000526103a05160e01b60045260086000208061358052602480350160206103a05102808260206135800137600435602401915060c0826135a083013760e0016135802083810661266081905290925090508281800961268052828161268051096126a05250806000526112e0516020526112c051604052611320516060526113005160805260a0600020905081810661260052806000526001602053506021600090812082810661262052815261136051602052611340516040526113a0516060526113805160805260a09020818106612640819052828180096134205282816134205109613440528281613440510961346052806134805250806000526113e0516020526113c05160405261142051606052611400516080526114605160a0526114405160c0526114a05160e052611480516101005261012060002090508181066126c052806126e0525061260051612620516103c051600180856001602480350160206103a0510281018360058a0984600c8b0999505b81831015610ea857823585811085169450858a82089050858183018909975085818c01880996505084888209905084888b099950602083019250610e69565b50505080610ec15763374a972f60e01b60005260046000fd5b50508161300052806130205250505050508081600161260051086126205109806103805160015b81811015610efd578483840992508001610ee8565b5050613100528181800990508181820961312052506126c05161038051819060015b81811015610f34578483840992508001610f1f565b50508061304052826001840382089050613400518084036103e051858286088684840992508687848808820990508684840992508687848808820990508687888686098808820990506103c051925086828609915086600188038708878485099450876001890389898b888d8b8c0909090896506130205194508493508782860994508488878709955085898388099650868a61312051890997508760206000526020805260206040528b8b8a0960605260028c036080528b60a0526020600060c0600060055afa61101157633e2529ef60e21b60005260046000fd5b60005198508b818a0990508b8b8a0998508b828a0991508b613120518a0998508b838a0992508b858a0998508b848a0993508b8a8a0998508b888a0997508b868a0998508b613020518d8b8c090998508b896130005109613060528b888b09613080528b848709613780528b8388096130a0528b826131005109613140528b8188096130c052505050505050505050505061264051506126005161262051828361190051840982611620510101846118e051850983611600510101098384611940518509836116605101018561192051860984611640510101098485868385096116a051096134805109858661198051870985611620510101876119605188098661160051010109925085866119c051870985611660510101876119a0518809866116405101010991508586878885870961208051096134805109870382089050856126405161348051096134805285868788613060518a0361208051086130c0510961348051098208905085612640516134805109613480528586878860018a036116a051086130a05109613480510982086136005250505050508061264051613480510961348052806117205161266051098182836120205161178051096116405108820890508161266051820990508182836120005161176051096116205108820890508161266051820990508182836119e0516117005109611600510882089050816118405183846126605161186051098586612680516118805109876126a0516118a05109080808826120c0518485612660516120e051098687612680516121005109886126a051612120510908080883846001612600510861262051098461262051866118c051870908935084818687612600518609860808925084838509935084856001612600510885099350846130a05161264051099250848385089350846116c0518509935084838603850893508481868761260051612060510961168051080892505050826130c05161342051098381850383089150836120a05183099150838461314051830983089150508261348051848386038508096136205250508061344051613480510961348052806116e0516116005109816117005161162051098261172051611640510983611740516116605109847f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000008687600389036117a0510888611760518a6116205161160051090909098586878889858a08880886088408611780510894505050505081828384856116605161160051086119e051870308611760510884600286036117a05108096126405109828384858685612040510887600189036117a051080985086117a05109613480510961364052505080613420516134805109613480526002810360038203826116005184036116205108836116205185036116405108846116405186036116605108856116605187036119e05108866134805188898888088a8b8b8a088c8a8e038e8c8d09080909099350868788612640516134805109898a8988088b8c8c8a088d8a8f038f8c8d090809090985089350868788613420516134805109898a8987088b8c8c89088d898f038f8b8c090809090985089350868788613440516134805109898a8986088b8c8c88088d888f038f8a8b090809090985089350505050836117c0518209613660525050613460516134805183925009613480528061172051828361162051856120005161200051080884611620516119e0518703090909816119e0516119e051098283611620518503612000510882099050826117405182099050826119e0516119e05109836119e05182099050838485611620516120005108866116205161162051090982089050838485611640516116405109866120405161204051090885038208905083611640516120405109848182089050846116e05182099050848583830886858708089250846134805184099250848561164051612020510886611720516119e0510909935084856120005187036116205108866116e05161204051090985039050848586612000518803611620510861164051098687611640516120205108611620510987030891508485612640516134805109868488858908080993505050826117e051848484080961368052505080613460516134805109613480528081611620516119e05109826120005161160051090881612020518303838461164051611620510985611660516116005109080882600160441b82099050826120405184038208905082828208905082611740518209905082600160441b830991508283612000516119e05109830891508261172051848561166051611640510886038508098361176051858661204051612020510887038761166051880808099250836117005185858786860808096136c0525050612000518291506140009009816119e0518208905081614000820990508161164051820890508161400082099050816116205182089050816140008209905081611600518208905081611660518303820890508161174051820990508161400061202051098261200051820890508261400082099050826119e05182089050826140008209905082611660518208905082614000820990508261164051820890508261204051840382089050826117605182099050826117205184838508096136e0525050806126605161164051098161162051820890508161266051820990508161160051820890508161266051820990508161178051820890508082611660518403830891508161374052826116005184036119e05108836116605185036120405108848560018703840883098586848803600108830991508585876126405189858b61264051890908090861372052856126605161202051099450856120005186089450856126605186099450856119e0518608945085612660518609945085858703612040510894508561164051870361202051089150858687878903600108840987858903600108099150858487036116605108868760018903830882099050868760018903880887099550866126405184099250868284089250866126405184099250868684089250866126405184099250868184089250508161370052505083611620518503612000510892508361164051850385868488036001088609089250836117005161372051099150838461174051850983089150838461176051613740510983089150836116e0518309915083846117a051613700510983089150836136c05183089250836136e05184089250836118005184099250836134805184099250826136a05283613440516134805109613480525050508061378051826136a0518461368051866136605188613640518a61362051613600510808080808096137608190526126e0516137a08190526137c0919091526102e460043501610520816137e03750506105606137a020818106612700526000819052600160205381602160002006612720526002602053816021600020066127405260036020538160216000200661276052600460205381602160002006612780526005602053816021600020066127a0526006602053816021600020066127c0526007602053816021600020066127e0526008602053816021600020066128005260096020538160216000200661282052600a6020538160216000200661284052600b6020538160216000200661286052600c6020538160216000200661288052600d602053816021600020066128a052600e602053816021600020066128c052600f602053816021600020066128e05260106020538160216000200661290052601160205381602160002006612920526012602053816021600020066129405260136020538160216000200661296052601460205381602160002006612980526015602053816021600020066129a0526016602053816021600020066129c0526017602053816021600020066129e052601860205381602160002006612a0052601960205381602160002006612a2052601a60205381602160002006612a4052601b60205381602160002006612a6052601c60205381602160002006612a8052601d60205381602160002006612aa052601d6020535060216000908120828106612ac05281526123205160205261230051604052612360516060526123405160805260a08120829006612b00526113c0516113e0518482800985600387838609088683840914935050816131605280602061316001525050611400516114205184828309856003878386090886838409148416935050816000528060205250506130405160405260406131a06060600060075afa16604061316060808160065afa81169050611440516114605184828309856003878386090886838409148416935050816000528060205250508161304051613040510960405260406131a06060600060075afa16604061316060808160065afa81169050611480516114a05184828309856003878386090886838409148416935050816000528060205250508161304051836130405161304051090960405260406131a06060600060075afa16604061316060808160065afa81169050611200516112205184828309856003878386090886838409148416935050816000528060205250508161270051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611240516112605184828309856003878386090886838409148416935050816000528060205250508161272051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611280516112a05184828309856003878386090886838409148416935050816000528060205250508161274051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa811690506112c0516112e05184828309856003878386090886838409148416935050816000528060205250508161276051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611300516113205184828309856003878386090886838409148416935050816000528060205250508161278051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa8116905061134051611360518482830985600387838609088683840914841693505081600052806020525050816127a051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611380516113a0518482830985600387838609088683840914841693505081600052806020525050816127c051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050610400516104205184828309856003878386090886838409148416935050816000528060205250506127e05160405260406131a06060600060075afa16604061316060808160065afa81169050610440516104605184828309856003878386090886838409148416935050816000528060205250506128005160405260406131a06060600060075afa16604061316060808160065afa81169050610480516104a05184828309856003878386090886838409148416935050816000528060205250506128205160405260406131a06060600060075afa16604061316060808160065afa811690506104c0516104e05184828309856003878386090886838409148416935050816000528060205250506128405160405260406131a06060600060075afa16604061316060808160065afa81169050610500516105205184828309856003878386090886838409148416935050816000528060205250506128605160405260406131a06060600060075afa16604061316060808160065afa81169050610540516105605184828309856003878386090886838409148416935050816000528060205250506128805160405260406131a06060600060075afa16604061316060808160065afa81169050610580516105a05184828309856003878386090886838409148416935050816000528060205250506128a05160405260406131a06060600060075afa16604061316060808160065afa811690506105c0516105e05184828309856003878386090886838409148416935050816000528060205250506128c05160405260406131a06060600060075afa16604061316060808160065afa81169050610600516106205184828309856003878386090886838409148416935050816000528060205250506128e05160405260406131a06060600060075afa16604061316060808160065afa81169050610640516106605184828309856003878386090886838409148416935050816000528060205250506129005160405260406131a06060600060075afa16604061316060808160065afa81169050610680516106a05184828309856003878386090886838409148416935050816000528060205250506129205160405260406131a06060600060075afa16604061316060808160065afa811690506106c0516106e05184828309856003878386090886838409148416935050816000528060205250506129405160405260406131a06060600060075afa16604061316060808160065afa81169050610700516107205184828309856003878386090886838409148416935050816000528060205250506129605160405260406131a06060600060075afa16604061316060808160065afa81169050610740516107605184828309856003878386090886838409148416935050816000528060205250506129805160405260406131a06060600060075afa16604061316060808160065afa81169050610780516107a0518482830985600387838609088683840914841693505081600052806020525050816129a051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa811690506107c0516107e0518482830985600387838609088683840914841693505081600052806020525050816129c051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa8116905061080051610820518482830985600387838609088683840914841693505081600052806020525050816129e051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa811690506108405161086051848283098560038783860908868384091484169350508160005280602052505081612a0051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050610880516108a0518482830985600387838609088683840914841693505081600052806020525050612a205160405260406131a06060600060075afa16604061316060808160065afa811690506108c0516108e0518482830985600387838609088683840914841693505081600052806020525050612a405160405260406131a06060600060075afa16604061316060808160065afa8116905061090051610920518482830985600387838609088683840914841693505081600052806020525050612a605160405260406131a06060600060075afa16604061316060808160065afa8116905061094051610960518482830985600387838609088683840914841693505081600052806020525050612a805160405260406131a06060600060075afa16604061316060808160065afa81169050610980516109a0518482830985600387838609088683840914841693505081600052806020525050612aa05160405260406131a06060600060075afa16604061316060808160065afa8116905081826116005184612b00516119e051090861270051098283846116205186612b00516120005109086127205109820890508283846116405186612b00516120205109086127405109820890508283846116605186612b00516120405109086127605109820890508283846116805186612b00516120605109086127805109820890508283846116a05186612b00516120805109086127a05109820890508283846116c05186612b00516120a05109086127c051098208905082836116e0516127e051098208905082836117005161280051098208905082836117205161282051098208905082836117405161284051098208905082836117605161286051098208905082836117805161288051098208905082836117a0516128a051098208905082836117c0516128c051098208905082836117e0516128e051098208905082836118005161290051098208905082836119605161292051098208905082836119805161294051098208905082836119a05161296051098208905082836119c0516129805109820890508283846118405186612b00516120c05109086129a05109820890508283846118605186612b00516120e05109086129c05109820890508283846118805186612b00516121005109086129e05109820890508283846118a05186612b0051612120510908612a0051098208905082836118c051612a2051098208905082836118e051612a40510982089050828361190051612a60510982089050828361192051612a80510982089050828361194051612aa0510982089050826137605182089050600160005260026020528083036040525060406131a06060600060075afa16604061316060808160065afa16613360819052612b00516126c05161230051612320518682800987600389838609088883840914955050816000528060205250508060405260406131a06060600060075afa831692506040613160608061316060065afa8316925061234051612360518682830987600389838609088883840914861695505081600052806020525050836103c05185838509096040525060406131a06060600060075afa821691506040613220608061316060065afa8216915061230051600052612320516020526123405160405261236051606052806080526040806060604060075afa8216915060406131e06080600060065afa82169150613200518403613200526109c05115612ad15761350051613520518582830986600388838609088783840914851694505081600052806020525050828182096040526040606080600060075afa8216915061354051613560518582830986600388838609088783840914851694505081600052806020525050604060006060600060075afa821691506132205160a0526132405160c05260406132206080606060065afa821691506131e0516040526132005160605260406131e06080600060065afa821691505b5080612ae85763f755f36960e01b60005260046000fd5b806133805261322051600052613240516020527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26040527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6080527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0526131e05160c0526132005160e052610a005161010052610a205161012052610a405161014052610a60516101605260206000610180600060085afa9050806133a0526000516133c05250505061336051613380516133c0516133a051161616612bff576301c47f3b60e21b60005260046000fd5b600160005260206000f35b60008060008060408587031215612c2057600080fd5b843567ffffffffffffffff80821115612c3857600080fd5b818701915087601f830112612c4c57600080fd5b813581811115612c5b57600080fd5b886020828501011115612c6d57600080fd5b602092830196509450908601359080821115612c8857600080fd5b818701915087601f830112612c9c57600080fd5b813581811115612cab57600080fd5b8860208260051b8501011115612cc057600080fd5b9598949750506020019450505056fea2646970667358221220b574d8b5efd582594a26998fb70c91556aee5a70cd43e2af9a141d70cc906adb64736f6c63430008120033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461006e575b600080fd5b6040517fd11f99e40c55d0ef202afc9d6497a56340bb8a86b5ceb40f13c6d96d72d9fcca81526020015b60405180910390f35b61008161007c366004612c0a565b610091565b6040519015158152602001610065565b620200006103805260376103a0527f1bf82deba7d74902c3708cc6e70e61f30512eca95655210e276e5858ce8f58e56103c0527f30643640b9f82f90e83b698e5ea6179c7c05542e859533b48b9953a2f53608016103e0527f245285cdf6c55535c4c72ecc89b3806ab342cd6e01bbb82b0c5c0113cba4a211610400527f1b565aa264e9d606df12185b82e6576a58d4513d864ed651927e961e461dcc86610420527f272dc56c0559a6089e4c3b48edd6c4c80fa911f5c041cbe3af06f7614bbbb43a610440527f18e69137e65a9875f4ee14c4880f5d0506defdade9186ba227b1e46a7652c0ed610460527f1f7131f4d583fc283d61e1c1053c70ab3ae7afbb4b2b4b95fbbd1c1430dabc16610480527f2a787bbadc7214d359b0feeabb1fdd0722801bdb1383aceeac392d3b8e4c40656104a0527f1735f148bd3f021f7e5401fb512f967181d442b239dd607d741d9924d9753ed46104c0527f19da04c1072f90dc7bdc09fc92b41b0f89d97347b8021ddd54fb8fba967b23316104e0527f031ad7e57c0c7113b369040cbfc3dd8de50d32e976e183e1c933096bef9c6a7f610500527f0f571b6887f7af84ec8c11b3d00705d218fd60433cf7f407ff610bc9e874017d610520527f2dddf1ada8a8d49f4437fbb93af9165e4af883c41a7ade0c4d714e11242703c5610540527f21ad6325b7bc4c8223416ba9d17ccecc6d5667cfe176791a5f02c6df49c9af5b610560527f245bf8a517b30344ac2e9c1387e2ffbfcb15877ccf9dc167f0c810d6cf763317610580527f2f200231a08e7beeffde231718ab0ab8dc9dbe96e0929a07d7adb342d012978a6105a0527f23ac6d2f41b030d51bbc19ccfb4648d70e875206a22124faddfa4d3fbd1352786105c0527f2d24acb1262a55fcef579f9249ddae57c5a20a84ec61d37fb845599824bb317a6105e0527f2e438eb058a779a5ad4135fd7e14d1145a038cc260c09cc8622bc19b90cf5dbe610600527f288504c94c6277a8b5004fc5dde949f0ce8c895e56d52e62d4f1c9175b19b45e610620527f1414af76247139fa9e8fef8b393a3e03227ee3a6fedb1e55f5db82cb2352782a610640527f2c7895a68d2fab5b2bce4d7703daebf9011e63d675bc6898c7f06087d6d83d99610660527f18b742204f0348b5c1b38c8a1a3698f99696f77b0739572ed32f5ff735587526610680527f180c4419454e91a4cf890444c937e108ffce7e3f88d86fcff3753c38b0a23f666106a0527f0a6ff425e08220154841bf2ca49c216137315a40781c7df12ce13543ab59a4cd6106c0527f1ae3a99295d617eecf7abde22269ebf78cc7060000dcb08a8c37d00f9e630a9b6106e0527f2132af6633a1cc574d02e157dad9a69b22c1f5caa5bbcc22db5a95132e3bf076610700527f2e79886ca28210ee429fd38d3727f549f2f91e1dee91e5f875f8b588d367b527610720527ec465601b3d03dffc34f62e0f11de17542c4a745b7a878ce754c1f4ad82bfae610740527e60c9633269601f6fcb01b6d26d46ee93055f807a2a1c9e7c33d186f04f65f8610760527f1f085b2095ee26145e167f353ef9a02dde005b3ba11bf60add10bdd9c00e7643610780527f0748759c43af1624acf605b6a23ebba01173cd346730c934d5fb7edd48413f946107a0527f2c8d2b9623692ab46021a60209f7148458ecb2ccdbbd766251f463ca7c53489a6107c0527f1aefa543256fc4b49dc193383f0156f7c331a2b89d0a0b5938a2fe2abe136d196107e0527f058ea36a362c899e3304278eca9a52fa74b07588d35cc5583278237cbbb53d68610800527f2afc5a5c85ca7b8fdac8a2b082096621e184e5a00a5cf1d481e28ad8071a691a610820527f14864cbfc194228094a325c4abf8260dbdca65e4883fce1425ec2933843b6737610840527f1489390b9b42c540c675cfea8acb88ceebe8c678f21ee8e8bee12af884fc1c3d610860527f2e6f974274a8b0d7c22721399c87384f68404226f622f0e50f9182fe4a9c7af3610880527f1bd608ba7bca523c9564c26bb23e27553fa0a0071e77a4123590e98b57860f096108a0527f1106ffa0e5b65066a1e6f54849a38c0fa40cd0f86edfb8c53de73175aa1a0aaa6108c0527f04caf81aa2aa53dd6a58b56d058005810cf634fbef2fd7945ee29aaa8744414a6108e0527f0acafc98985553ff731f444d22822ca2054385216d1e9f003b84868dfef67f5a610900527f059fc7ed336de83aac1273db4f51760b61cba1a42f3495738653ab46370dde76610920527f2d6688fcab60e29a560b4e4e03e0cc0d9e43dfb8d5b192e722d72a0e3adafdaf610940527f02bbd2a1bd7674a5b4e764db185aa85418f61b44c800329a3c43893f07a3c35a610960527f2e68f5b79c21422d3a849acc310202e3507f9ffd78d24d930c2b764393cd3e8f610980527f018e8379fcfaa214c9b07a4d500b14c6b03f2e218423a61c59d6e569a6a77a6e6109a05260006109c08190526109e08190527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1610a00527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0610a20527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4610a40527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55610a60527f244cf010c43ca87237d8b00bf9dd50c4c01c7f086bd4e8c920e75251d96f0d22613400526103a05182811461088657604051637667dc9b60e01b8152600481018290526024810184905260440160405180910390fd5b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd477f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016024600435018281350661122052826020820135066112005282604082013506611260528260608201350661124052826080820135066112a0528260a082013506611280528260c0820135066112e0528260e0820135066112c05282610100820135066113205282610120820135066113005282610140820135066113605282610160820135066113405282610180820135066113a052826101a08201350661138052826101c0820135066113e052826101e0820135066113c05282610200820135066114205282610220820135066114005282610240820135066114605282610260820135066114405282610280820135066114a052826102a08201350661148052816102c08201350661160052816102e0820135066116205281610300820135066116405281610320820135066116605281610340820135066116805281610360820135066116a05281610380820135066116c052816103a0820135066116e052816103c08201350661170052816103e0820135066117205281610400820135066117405281610420820135066117605281610440820135066117805281610460820135066117a05281610480820135066117c052816104a0820135066117e052816104c08201350661180052816104e0820135066119605281610500820135066119805281610520820135066119a05281610540820135066119c052816105608201350661184052816105808201350661186052816105a08201350661188052816105c0820135066118a052816105e0820135066118c05281610600820135066118e05281610620820135066119005281610640820135066119205281610660820135066119405281610680820135066119e052816106a08201350661200052816106c08201350661202052816106e0820135066120405281610700820135066120605281610720820135066120805281610740820135066120a05281610760820135066120c05281610780820135066120e052816107a08201350661210052816107c08201350661212052826107e08201350661232052826108008201350661230052826108208201350661236052826108408201350661234052506109c05115610ce8576024803501806109e05160051b0190508035602082013560441b81019050604082013560881b81019050606082013560cc1b81019050608082013560a083013560441b8101905060c083013560881b8101905060e083013560cc1b8101905061010083013561012084013560441b8101905061014084013560881b8101905061016084013560cc1b810190506101808401356101a085013560441b810190506101c085013560881b810190506101e085013560cc1b810190508361350052826135205281613540528061356052868110878410168783108886101616610ce2576375d4fa5360e11b60005260046000fd5b50505050505b6103805160e01b6000526103a05160e01b60045260086000208061358052602480350160206103a05102808260206135800137600435602401915060c0826135a083013760e0016135802083810661266081905290925090508281800961268052828161268051096126a05250806000526112e0516020526112c051604052611320516060526113005160805260a0600020905081810661260052806000526001602053506021600090812082810661262052815261136051602052611340516040526113a0516060526113805160805260a09020818106612640819052828180096134205282816134205109613440528281613440510961346052806134805250806000526113e0516020526113c05160405261142051606052611400516080526114605160a0526114405160c0526114a05160e052611480516101005261012060002090508181066126c052806126e0525061260051612620516103c051600180856001602480350160206103a0510281018360058a0984600c8b0999505b81831015610ea857823585811085169450858a82089050858183018909975085818c01880996505084888209905084888b099950602083019250610e69565b50505080610ec15763374a972f60e01b60005260046000fd5b50508161300052806130205250505050508081600161260051086126205109806103805160015b81811015610efd578483840992508001610ee8565b5050613100528181800990508181820961312052506126c05161038051819060015b81811015610f34578483840992508001610f1f565b50508061304052826001840382089050613400518084036103e051858286088684840992508687848808820990508684840992508687848808820990508687888686098808820990506103c051925086828609915086600188038708878485099450876001890389898b888d8b8c0909090896506130205194508493508782860994508488878709955085898388099650868a61312051890997508760206000526020805260206040528b8b8a0960605260028c036080528b60a0526020600060c0600060055afa61101157633e2529ef60e21b60005260046000fd5b60005198508b818a0990508b8b8a0998508b828a0991508b613120518a0998508b838a0992508b858a0998508b848a0993508b8a8a0998508b888a0997508b868a0998508b613020518d8b8c090998508b896130005109613060528b888b09613080528b848709613780528b8388096130a0528b826131005109613140528b8188096130c052505050505050505050505061264051506126005161262051828361190051840982611620510101846118e051850983611600510101098384611940518509836116605101018561192051860984611640510101098485868385096116a051096134805109858661198051870985611620510101876119605188098661160051010109925085866119c051870985611660510101876119a0518809866116405101010991508586878885870961208051096134805109870382089050856126405161348051096134805285868788613060518a0361208051086130c0510961348051098208905085612640516134805109613480528586878860018a036116a051086130a05109613480510982086136005250505050508061264051613480510961348052806117205161266051098182836120205161178051096116405108820890508161266051820990508182836120005161176051096116205108820890508161266051820990508182836119e0516117005109611600510882089050816118405183846126605161186051098586612680516118805109876126a0516118a05109080808826120c0518485612660516120e051098687612680516121005109886126a051612120510908080883846001612600510861262051098461262051866118c051870908935084818687612600518609860808925084838509935084856001612600510885099350846130a05161264051099250848385089350846116c0518509935084838603850893508481868761260051612060510961168051080892505050826130c05161342051098381850383089150836120a05183099150838461314051830983089150508261348051848386038508096136205250508061344051613480510961348052806116e0516116005109816117005161162051098261172051611640510983611740516116605109847f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000008687600389036117a0510888611760518a6116205161160051090909098586878889858a08880886088408611780510894505050505081828384856116605161160051086119e051870308611760510884600286036117a05108096126405109828384858685612040510887600189036117a051080985086117a05109613480510961364052505080613420516134805109613480526002810360038203826116005184036116205108836116205185036116405108846116405186036116605108856116605187036119e05108866134805188898888088a8b8b8a088c8a8e038e8c8d09080909099350868788612640516134805109898a8988088b8c8c8a088d8a8f038f8c8d090809090985089350868788613420516134805109898a8987088b8c8c89088d898f038f8b8c090809090985089350868788613440516134805109898a8986088b8c8c88088d888f038f8a8b090809090985089350505050836117c0518209613660525050613460516134805183925009613480528061172051828361162051856120005161200051080884611620516119e0518703090909816119e0516119e051098283611620518503612000510882099050826117405182099050826119e0516119e05109836119e05182099050838485611620516120005108866116205161162051090982089050838485611640516116405109866120405161204051090885038208905083611640516120405109848182089050846116e05182099050848583830886858708089250846134805184099250848561164051612020510886611720516119e0510909935084856120005187036116205108866116e05161204051090985039050848586612000518803611620510861164051098687611640516120205108611620510987030891508485612640516134805109868488858908080993505050826117e051848484080961368052505080613460516134805109613480528081611620516119e05109826120005161160051090881612020518303838461164051611620510985611660516116005109080882600160441b82099050826120405184038208905082828208905082611740518209905082600160441b830991508283612000516119e05109830891508261172051848561166051611640510886038508098361176051858661204051612020510887038761166051880808099250836117005185858786860808096136c0525050612000518291506140009009816119e0518208905081614000820990508161164051820890508161400082099050816116205182089050816140008209905081611600518208905081611660518303820890508161174051820990508161400061202051098261200051820890508261400082099050826119e05182089050826140008209905082611660518208905082614000820990508261164051820890508261204051840382089050826117605182099050826117205184838508096136e0525050806126605161164051098161162051820890508161266051820990508161160051820890508161266051820990508161178051820890508082611660518403830891508161374052826116005184036119e05108836116605185036120405108848560018703840883098586848803600108830991508585876126405189858b61264051890908090861372052856126605161202051099450856120005186089450856126605186099450856119e0518608945085612660518609945085858703612040510894508561164051870361202051089150858687878903600108840987858903600108099150858487036116605108868760018903830882099050868760018903880887099550866126405184099250868284089250866126405184099250868684089250866126405184099250868184089250508161370052505083611620518503612000510892508361164051850385868488036001088609089250836117005161372051099150838461174051850983089150838461176051613740510983089150836116e0518309915083846117a051613700510983089150836136c05183089250836136e05184089250836118005184099250836134805184099250826136a05283613440516134805109613480525050508061378051826136a0518461368051866136605188613640518a61362051613600510808080808096137608190526126e0516137a08190526137c0919091526102e460043501610520816137e03750506105606137a020818106612700526000819052600160205381602160002006612720526002602053816021600020066127405260036020538160216000200661276052600460205381602160002006612780526005602053816021600020066127a0526006602053816021600020066127c0526007602053816021600020066127e0526008602053816021600020066128005260096020538160216000200661282052600a6020538160216000200661284052600b6020538160216000200661286052600c6020538160216000200661288052600d602053816021600020066128a052600e602053816021600020066128c052600f602053816021600020066128e05260106020538160216000200661290052601160205381602160002006612920526012602053816021600020066129405260136020538160216000200661296052601460205381602160002006612980526015602053816021600020066129a0526016602053816021600020066129c0526017602053816021600020066129e052601860205381602160002006612a0052601960205381602160002006612a2052601a60205381602160002006612a4052601b60205381602160002006612a6052601c60205381602160002006612a8052601d60205381602160002006612aa052601d6020535060216000908120828106612ac05281526123205160205261230051604052612360516060526123405160805260a08120829006612b00526113c0516113e0518482800985600387838609088683840914935050816131605280602061316001525050611400516114205184828309856003878386090886838409148416935050816000528060205250506130405160405260406131a06060600060075afa16604061316060808160065afa81169050611440516114605184828309856003878386090886838409148416935050816000528060205250508161304051613040510960405260406131a06060600060075afa16604061316060808160065afa81169050611480516114a05184828309856003878386090886838409148416935050816000528060205250508161304051836130405161304051090960405260406131a06060600060075afa16604061316060808160065afa81169050611200516112205184828309856003878386090886838409148416935050816000528060205250508161270051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611240516112605184828309856003878386090886838409148416935050816000528060205250508161272051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611280516112a05184828309856003878386090886838409148416935050816000528060205250508161274051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa811690506112c0516112e05184828309856003878386090886838409148416935050816000528060205250508161276051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611300516113205184828309856003878386090886838409148416935050816000528060205250508161278051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa8116905061134051611360518482830985600387838609088683840914841693505081600052806020525050816127a051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050611380516113a0518482830985600387838609088683840914841693505081600052806020525050816127c051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050610400516104205184828309856003878386090886838409148416935050816000528060205250506127e05160405260406131a06060600060075afa16604061316060808160065afa81169050610440516104605184828309856003878386090886838409148416935050816000528060205250506128005160405260406131a06060600060075afa16604061316060808160065afa81169050610480516104a05184828309856003878386090886838409148416935050816000528060205250506128205160405260406131a06060600060075afa16604061316060808160065afa811690506104c0516104e05184828309856003878386090886838409148416935050816000528060205250506128405160405260406131a06060600060075afa16604061316060808160065afa81169050610500516105205184828309856003878386090886838409148416935050816000528060205250506128605160405260406131a06060600060075afa16604061316060808160065afa81169050610540516105605184828309856003878386090886838409148416935050816000528060205250506128805160405260406131a06060600060075afa16604061316060808160065afa81169050610580516105a05184828309856003878386090886838409148416935050816000528060205250506128a05160405260406131a06060600060075afa16604061316060808160065afa811690506105c0516105e05184828309856003878386090886838409148416935050816000528060205250506128c05160405260406131a06060600060075afa16604061316060808160065afa81169050610600516106205184828309856003878386090886838409148416935050816000528060205250506128e05160405260406131a06060600060075afa16604061316060808160065afa81169050610640516106605184828309856003878386090886838409148416935050816000528060205250506129005160405260406131a06060600060075afa16604061316060808160065afa81169050610680516106a05184828309856003878386090886838409148416935050816000528060205250506129205160405260406131a06060600060075afa16604061316060808160065afa811690506106c0516106e05184828309856003878386090886838409148416935050816000528060205250506129405160405260406131a06060600060075afa16604061316060808160065afa81169050610700516107205184828309856003878386090886838409148416935050816000528060205250506129605160405260406131a06060600060075afa16604061316060808160065afa81169050610740516107605184828309856003878386090886838409148416935050816000528060205250506129805160405260406131a06060600060075afa16604061316060808160065afa81169050610780516107a0518482830985600387838609088683840914841693505081600052806020525050816129a051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa811690506107c0516107e0518482830985600387838609088683840914841693505081600052806020525050816129c051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa8116905061080051610820518482830985600387838609088683840914841693505081600052806020525050816129e051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa811690506108405161086051848283098560038783860908868384091484169350508160005280602052505081612a0051836001612b0051080960405260406131a06060600060075afa16604061316060808160065afa81169050610880516108a0518482830985600387838609088683840914841693505081600052806020525050612a205160405260406131a06060600060075afa16604061316060808160065afa811690506108c0516108e0518482830985600387838609088683840914841693505081600052806020525050612a405160405260406131a06060600060075afa16604061316060808160065afa8116905061090051610920518482830985600387838609088683840914841693505081600052806020525050612a605160405260406131a06060600060075afa16604061316060808160065afa8116905061094051610960518482830985600387838609088683840914841693505081600052806020525050612a805160405260406131a06060600060075afa16604061316060808160065afa81169050610980516109a0518482830985600387838609088683840914841693505081600052806020525050612aa05160405260406131a06060600060075afa16604061316060808160065afa8116905081826116005184612b00516119e051090861270051098283846116205186612b00516120005109086127205109820890508283846116405186612b00516120205109086127405109820890508283846116605186612b00516120405109086127605109820890508283846116805186612b00516120605109086127805109820890508283846116a05186612b00516120805109086127a05109820890508283846116c05186612b00516120a05109086127c051098208905082836116e0516127e051098208905082836117005161280051098208905082836117205161282051098208905082836117405161284051098208905082836117605161286051098208905082836117805161288051098208905082836117a0516128a051098208905082836117c0516128c051098208905082836117e0516128e051098208905082836118005161290051098208905082836119605161292051098208905082836119805161294051098208905082836119a05161296051098208905082836119c0516129805109820890508283846118405186612b00516120c05109086129a05109820890508283846118605186612b00516120e05109086129c05109820890508283846118805186612b00516121005109086129e05109820890508283846118a05186612b0051612120510908612a0051098208905082836118c051612a2051098208905082836118e051612a40510982089050828361190051612a60510982089050828361192051612a80510982089050828361194051612aa0510982089050826137605182089050600160005260026020528083036040525060406131a06060600060075afa16604061316060808160065afa16613360819052612b00516126c05161230051612320518682800987600389838609088883840914955050816000528060205250508060405260406131a06060600060075afa831692506040613160608061316060065afa8316925061234051612360518682830987600389838609088883840914861695505081600052806020525050836103c05185838509096040525060406131a06060600060075afa821691506040613220608061316060065afa8216915061230051600052612320516020526123405160405261236051606052806080526040806060604060075afa8216915060406131e06080600060065afa82169150613200518403613200526109c05115612ad15761350051613520518582830986600388838609088783840914851694505081600052806020525050828182096040526040606080600060075afa8216915061354051613560518582830986600388838609088783840914851694505081600052806020525050604060006060600060075afa821691506132205160a0526132405160c05260406132206080606060065afa821691506131e0516040526132005160605260406131e06080600060065afa821691505b5080612ae85763f755f36960e01b60005260046000fd5b806133805261322051600052613240516020527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26040527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6080527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0526131e05160c0526132005160e052610a005161010052610a205161012052610a405161014052610a60516101605260206000610180600060085afa9050806133a0526000516133c05250505061336051613380516133c0516133a051161616612bff576301c47f3b60e21b60005260046000fd5b600160005260206000f35b60008060008060408587031215612c2057600080fd5b843567ffffffffffffffff80821115612c3857600080fd5b818701915087601f830112612c4c57600080fd5b813581811115612c5b57600080fd5b886020828501011115612c6d57600080fd5b602092830196509450908601359080821115612c8857600080fd5b818701915087601f830112612c9c57600080fd5b813581811115612cab57600080fd5b8860208260051b8501011115612cc057600080fd5b9598949750506020019450505056fea2646970667358221220b574d8b5efd582594a26998fb70c91556aee5a70cd43e2af9a141d70cc906adb64736f6c63430008120033

Deployed Bytecode Sourcemap

135023:420:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135074:160;;;301:66;160:25:1;;148:2;133:18;135074:160:0;;;;;;;;22583:112433;;;;;;:::i;:::-;;:::i;:::-;;;1447:14:1;;1440:22;1422:41;;1410:2;1395:18;22583:112433:0;1282:187:1;22583:112433:0;523:66;7521:5;500:90;646:66;630:14;623:90;767:66;751:14;744:90;887:66;871:14;864:90;1012:66;996:14;989:90;1127:66;1111:14;1104:90;1242:66;1226:14;1219:90;1357:66;1341:14;1334:90;1473:66;1456:15;1449:91;1589:66;1572:15;1565:91;1705:66;1688:15;1681:91;1821:66;1804:15;1797:91;1937:66;1920:15;1913:91;2054:66;2037:15;2030:91;2171:66;2154:15;2147:91;2288:66;2271:15;2264:91;2405:66;2388:15;2381:91;2531:66;2514:15;2507:91;2657:66;2640:15;2633:91;2776:66;2759:15;2752:91;2895:66;2878:15;2871:91;3019:66;3002:15;2995:91;3143:66;3126:15;3119:91;3262:66;3245:15;3238:91;3381:66;3364:15;3357:91;3501:66;3484:15;3477:91;3621:66;3604:15;3597:91;3741:66;3724:15;3717:91;3861:66;3844:15;3837:91;3981:66;3964:15;3957:91;4101:66;4084:15;4077:91;4221:66;4204:15;4197:91;4341:66;4324:15;4317:91;4461:66;4444:15;4437:91;4581:66;4564:15;4557:91;4701:66;4684:15;4677:91;4821:66;4804:15;4797:91;4941:66;4924:15;4917:91;5061:66;5044:15;5037:91;5181:66;5164:15;5157:91;5301:66;5284:15;5277:91;5425:66;5408:15;5401:91;5549:66;5532:15;5525:91;5666:66;5649:15;5642:91;5783:66;5766:15;5759:91;5900:66;5883:15;5876:91;6017:66;6000:15;5993:91;6134:66;6117:15;6110:91;6251:66;6234:15;6227:91;6368:66;6351:15;6344:91;22679:4;6468:15;6461:29;;;6542:15;6535:26;;;6642:66;6625:15;6618:91;6764:66;6747:15;6740:91;6886:66;6869:15;6862:91;7008:66;6991:15;6984:91;7131:66;18611:6;7106:92;22855:14;22849:21;22895:48;;;22891:162;;22967:74;;-1:-1:-1;;;22967:74:0;;;;;1648:25:1;;;1689:18;;;1682:34;;;1621:18;;22967:74:0;;;;;;;22891:162;23098:77;23216;23464:4;23457;23444:18;23440:29;23534:1;23523:8;23510:22;23506:30;23496:8;23489:48;23611:1;23603:4;23593:8;23589:19;23576:33;23572:41;23562:8;23555:59;23690:1;23682:4;23672:8;23668:19;23655:33;23651:41;23641:8;23634:59;23767:1;23759:4;23749:8;23745:19;23732:33;23728:41;23718:8;23711:59;23846:1;23838:4;23828:8;23824:19;23811:33;23807:41;23797:8;23790:59;23923:1;23915:4;23905:8;23901:19;23888:33;23884:41;23874:8;23867:59;24002:1;23994:4;23984:8;23980:19;23967:33;23963:41;23953:8;23946:59;24079:1;24071:4;24061:8;24057:19;24044:33;24040:41;24030:8;24023:59;24158:1;24149:5;24139:8;24135:20;24122:34;24118:42;24109:7;24102:59;24235:1;24226:5;24216:8;24212:20;24199:34;24195:42;24186:7;24179:59;24312:1;24303:5;24293:8;24289:20;24276:34;24272:42;24263:7;24256:59;24389:1;24380:5;24370:8;24366:20;24353:34;24349:42;24340:7;24333:59;24473:1;24464:5;24454:8;24450:20;24437:34;24433:42;24417:14;24410:66;24557:1;24548:5;24538:8;24534:20;24521:34;24517:42;24501:14;24494:66;24635:1;24626:5;24616:8;24612:20;24599:34;24595:42;24585:8;24578:60;24713:1;24704:5;24694:8;24690:20;24677:34;24673:42;24663:8;24656:60;24793:1;24784:5;24774:8;24770:20;24757:34;24753:42;24743:8;24736:60;24871:1;24862:5;24852:8;24848:20;24835:34;24831:42;24821:8;24814:60;24951:1;24942:5;24932:8;24928:20;24915:34;24911:42;24901:8;24894:60;25029:1;25020:5;25010:8;25006:20;24993:34;24989:42;24979:8;24972:60;25109:1;25100:5;25090:8;25086:20;25073:34;25069:42;25059:8;25052:60;25187:1;25178:5;25168:8;25164:20;25151:34;25147:42;25137:8;25130:60;25270:1;25261:5;25251:8;25247:20;25234:34;25230:42;25217:11;25210:63;25351:1;25342:5;25332:8;25328:20;25315:34;25311:42;25298:11;25291:63;25432:1;25423:5;25413:8;25409:20;25396:34;25392:42;25379:11;25372:63;25513:1;25504:5;25494:8;25490:20;25477:34;25473:42;25460:11;25453:63;25593:1;25584:5;25574:8;25570:20;25557:34;25553:42;25541:10;25534:62;25673:1;25664:5;25654:8;25650:20;25637:34;25633:42;25621:10;25614:62;25760:1;25751:5;25741:8;25737:20;25724:34;25720:42;25701:17;25694:69;25841:1;25832:5;25822:8;25818:20;25805:34;25801:42;25788:11;25781:63;25922:1;25913:5;25903:8;25899:20;25886:34;25882:42;25869:11;25862:63;26003:1;25994:5;25984:8;25980:20;25967:34;25963:42;25950:11;25943:63;26084:1;26075:5;26065:8;26061:20;26048:34;26044:42;26031:11;26024:63;26165:1;26156:5;26146:8;26142:20;26129:34;26125:42;26112:11;26105:63;26246:1;26237:5;26227:8;26223:20;26210:34;26206:42;26193:11;26186:63;26331:1;26322:5;26312:8;26308:20;26295:34;26291:42;26274:15;26267:67;26415:1;26406:5;26396:8;26392:20;26379:34;26375:42;26359:14;26352:66;26503:1;26494:5;26484:8;26480:20;26467:34;26463:42;26443:18;26436:70;26586:1;26577:5;26567:8;26563:20;26550:34;26546:42;26531:13;26524:65;26673:1;26664:5;26654:8;26650:20;26637:34;26633:42;26616:15;26609:67;26758:1;26749:5;26739:8;26735:20;26722:34;26718:42;26701:15;26694:67;26845:1;26836:5;26826:8;26822:20;26809:34;26805:42;26788:15;26781:67;26930:1;26921:5;26911:8;26907:20;26894:34;26890:42;26873:15;26866:67;27017:1;27008:5;26998:8;26994:20;26981:34;26977:42;26960:15;26953:67;27102:1;27093:5;27083:8;27079:20;27066:34;27062:42;27045:15;27038:67;27187:1;27178:5;27168:8;27164:20;27151:34;27147:42;27130:15;27123:67;27272:1;27263:5;27253:8;27249:20;27236:34;27232:42;27215:15;27208:67;27361:1;27352:5;27342:8;27338:20;27325:34;27321:42;27300:19;27293:71;27445:1;27436:5;27426:8;27422:20;27409:34;27405:42;27391:12;27384:64;27527:1;27518:5;27508:8;27504:20;27491:34;27487:42;27473:12;27466:64;27609:1;27600:5;27590:8;27586:20;27573:34;27569:42;27555:12;27548:64;27691:1;27682:5;27672:8;27668:20;27655:34;27651:42;27637:12;27630:64;27780:1;27771:5;27761:8;27757:20;27744:34;27740:42;27721:17;27714:69;27867:1;27858:5;27848:8;27844:20;27831:34;27827:42;27808:17;27801:69;27954:1;27945:5;27935:8;27931:20;27918:34;27914:42;27895:17;27888:69;28041:1;28032:5;28022:8;28018:20;28005:34;28001:42;27982:17;27975:69;28127:1;28118:5;28108:8;28104:20;28091:34;28087:42;28069:16;28062:68;28215:1;28206:5;28196:8;28192:20;28179:34;28175:42;28157:16;28150:68;28310:1;28301:5;28291:8;28287:20;28274:34;28270:42;28245:23;28238:75;28401:1;28392:5;28382:8;28378:20;28365:34;28361:42;28338:21;28331:73;28492:1;28483:5;28473:8;28469:20;28456:34;28452:42;28429:21;28422:73;28583:1;28574:5;28564:8;28560:20;28547:34;28543:42;28520:21;28513:73;28674:1;28665:5;28655:8;28651:20;28638:34;28634:42;28611:21;28604:73;28756:1;28747:5;28737:8;28733:20;28720:34;28716:42;28704:10;28697:62;28836:1;28827:5;28817:8;28813:20;28800:34;28796:42;28784:10;28777:62;28924:1;28915:5;28905:8;28901:20;28888:34;28884:42;28866:16;28859:68;29010:1;29001:5;28991:8;28987:20;28974:34;28970:42;28952:16;28945:68;;29155:28;29149:35;29146:2070;;;29257:4;29250;29237:18;29233:29;29366:17;29322:40;29316:47;29313:1;29309:55;29305:79;29284:100;;29431:13;29418:27;29521:4;29506:13;29502:24;29489:38;29485:2;29481:47;29477:2;29473:56;29467:62;;29606:4;29591:13;29587:24;29574:38;29569:3;29565:48;29561:2;29557:57;29551:63;;29691:4;29676:13;29672:24;29659:38;29654:3;29650:48;29646:2;29642:57;29636:63;;29763:4;29748:13;29744:24;29731:38;29845:4;29830:13;29826:24;29813:38;29809:2;29805:47;29801:2;29797:56;29791:62;;29930:4;29915:13;29911:24;29898:38;29893:3;29889:48;29885:2;29881:57;29875:63;;30015:4;30000:13;29996:24;29983:38;29978:3;29974:48;29970:2;29966:57;29960:63;;30087:5;30072:13;30068:25;30055:39;30170:5;30155:13;30151:25;30138:39;30134:2;30130:48;30126:2;30122:57;30116:63;;30256:5;30241:13;30237:25;30224:39;30219:3;30215:49;30211:2;30207:58;30201:64;;30342:5;30327:13;30323:25;30310:39;30305:3;30301:49;30297:2;30293:58;30287:64;;30415:5;30400:13;30396:25;30383:39;30498:5;30483:13;30479:25;30466:39;30462:2;30458:48;30454:2;30450:57;30444:63;;30584:5;30569:13;30565:25;30552:39;30547:3;30543:49;30539:2;30535:58;30529:64;;30670:5;30655:13;30651:25;30638:39;30633:3;30629:49;30625:2;30621:58;30615:64;;30728:2;30708:18;30701:30;30780:2;30760:18;30753:30;30832:2;30812:18;30805:30;30884:2;30864:18;30857:30;31039:1;31035:2;31032:9;31028:1;31024:2;31021:9;31017:25;31012:1;31008:2;31005:9;31001:1;30997:2;30994:9;30990:25;30986:57;30976:221;;-1:-1:-1;;;31079:4:0;31072:58;31169:4;31163;31156:18;30976:221;;;;;;29146:2070;31383:5;31377:12;31372:3;31368:22;31362:4;31355:36;31437:14;31431:21;31426:3;31422:31;31416:4;31409:45;31505:4;31499;31489:21;31651:9;31622:27;31615:46;31861:4;31854;31841:18;31837:29;31984:4;31967:14;31961:21;31957:32;32081:17;32060:19;32053:4;32024:27;32020:38;32007:92;32278:4;32265:18;32285:4;32261:29;;-1:-1:-1;32394:16:0;32261:29;32325:38;32321:62;;32308:103;32573:51;;32667:27;32657:60;32769:17;;;32815:9;32808:22;;;32657:60;;-1:-1:-1;32769:17:0;-1:-1:-1;32784:1:0;32769:17;;32874:19;32859:13;32852:42;32973:1;32968:3;32952:13;32946:20;32939:36;32923:14;32916:60;;33114:9;33108:4;33101:23;33161:8;33155:15;33149:4;33142:29;33208:8;33202:15;33196:4;33189:29;33255:7;33249:14;33243:4;33236:28;33301:7;33295:14;33289:4;33282:28;33357:4;33351;33341:21;33328:34;;33414:1;33403:9;33399:17;33387:10;33380:37;33537:9;33531:4;33524:23;33579:4;33573;33565:19;-1:-1:-1;33631:4:0;33625;33615:21;;;33674:17;;;33661:11;33654:38;33799:23;;33859:7;33853:14;-1:-1:-1;33840:28:0;-1:-1:-1;33899:14:0;33893:4;33886:28;33951:14;33945:21;33939:4;33932:35;34004:14;33998:21;33992:4;33985:35;34067:4;34051:21;;34110:17;;;34097:11;34090:38;;;33689:1;34110:17;;34346:23;34329:15;34322:48;34451:1;34444:5;34426:15;34420:22;34413:40;34395:16;34388:66;34536:1;34529:5;34510:16;34504:23;34497:41;34479:16;34472:67;34582:5;34564:16;34557:31;;34707:9;34701:4;34694:23;34754:8;34748:15;34742:4;34735:29;34801:8;34795:15;34789:4;34782:29;34848:8;34842:15;34836:4;34829:29;34895:8;34889:15;34883:4;34876:29;34942:8;34936:15;34930:4;34923:29;34989:8;34983:15;34977:4;34970:29;35036:8;35030:15;35024:4;35017:29;35084:8;35078:15;35071:5;35064:30;35143:5;35137:4;35127:22;35114:35;;35203:1;35192:9;35188:17;35176:10;35169:37;35246:9;35231:13;35224:32;;35575:10;35569:17;35629:11;35623:18;35688:9;35682:16;35745:1;35789;35825;35900:4;36102;36095;36082:18;36078:29;36307:4;36290:14;36284:21;36280:32;36261:17;36257:56;36405:7;36399:4;36393;36386:27;36512:7;36506:4;36500;36493:27;36479:41;;36614:1095;36643:12;36624:17;36621:35;36614:1095;;;37210:17;37197:31;37294:7;37287:5;37284:18;37270:12;37266:37;37250:53;;37358:7;37351:5;37344;37337:29;37325:41;;37452:7;37445:4;37437:6;37433:17;37416:15;37409:51;37390:70;;37548:7;37541:4;37533:6;37529:17;37510;37503:53;37482:74;;;37616:7;37605:9;37597:6;37590:34;37580:44;;37682:7;37671:9;37663:6;37656:34;37646:44;;36703:4;36684:17;36680:28;36659:49;;36614:1095;;;36618:2;;;37821:12;37811:146;;-1:-1:-1;;;37865:4:0;37858:40;37933:4;37927;37920:18;37811:146;;;38005:15;37984:19;37977:44;38069:17;38046:21;38039:48;;;;;;38362:1;38358;38355;38342:10;38336:17;38329:31;38315:11;38309:18;38302:62;38405:10;38478:5;38472:12;38519:1;38542:170;38559:8;38552:5;38549:19;38542:170;;;38687:1;38670:15;38653;38646:43;38627:62;-1:-1:-1;38580:17:0;;38542:170;;;-1:-1:-1;;38756:27:0;38749:52;38877:1;38865:10;;38846:33;38821:58;;38963:1;38944:17;38925;38918:47;38990:29;38983:56;-1:-1:-1;40338:10:0;40332:17;40557:5;40551:12;40332:17;;40598:1;40621:182;40638:8;40631:5;40628:19;40621:182;;;40778:1;40757:19;40736;40729:51;40706:74;-1:-1:-1;40659:17:0;;40621:182;;;40625:2;;40863:19;40847:14;40840:43;40963:1;40959;40956;40952:9;40931:19;40924:41;40901:64;;41016:17;41010:24;41076:17;41073:1;41069:25;41140:18;41134:25;41232:1;41221:9;41215:4;41208:26;41302:1;41283:17;41272:9;41265:39;41252:52;;41405:1;41401;41390:9;41384:4;41377:26;41354:21;41347:60;41322:85;;41475:1;41456:17;41445:9;41438:39;41425:52;;41578:1;41574;41563:9;41557:4;41550:26;41527:21;41520:60;41495:85;;41732:1;41728;41724;41705:17;41694:9;41687:39;41681:4;41674:56;41651:21;41644:90;41598:136;;41773:9;41767:16;41754:29;;41873:1;41857:14;41836:19;41829:46;41803:72;;41944:1;41940;41937;41933:9;41927:4;41920:26;42016:1;42005:9;41994;41987:31;41966:52;;42216:1;42212;42209;42205:9;42201:1;42195:4;42191:1;42180:9;42176:1;42157:17;42138;42131:47;42124:69;42117:86;42084:156;42038:202;;42407:21;42401:28;42382:47;;42457:11;42447:21;;42544:1;42521:21;42508:11;42501:45;42486:60;;42574:11;42659:1;42638:19;42625:11;42618:43;42603:58;;42689:11;42774:1;42753:19;42740:11;42733:43;42718:58;;42804:11;42906:1;42874:29;42868:36;42855:11;42848:60;42833:75;;42936:11;42998:4;42995:1;42988:15;43038:4;43032;43025:18;43078:4;43072;43065:18;43157:1;43138:17;43125:11;43118:41;43112:4;43105:55;43202:1;43199;43195:9;43189:4;43182:23;43240:1;43234:4;43227:15;43316:4;43310;43304;43298;43292;43285:5;43274:47;43264:190;;-1:-1:-1;;;43357:3:0;43350:37;43426:4;43420;43413:18;43264:190;43497:4;43491:11;43476:26;;43571:1;43567:2;43554:11;43547:26;43541:32;;43645:1;43626:17;43613:11;43606:41;43591:56;;43697:1;43693:2;43680:11;43673:26;43667:32;;43790:1;43758:29;43752:36;43739:11;43732:60;43717:75;;43842:1;43838:2;43825:11;43818:26;43812:32;;43918:1;43897:19;43884:11;43877:43;43862:58;;43970:1;43966:2;43953:11;43946:26;43940:32;;44046:1;44025:19;44012:11;44005:43;43990:58;;44098:1;44094:2;44081:11;44074:26;44068:32;;44176:1;44153:21;44140:11;44133:45;44118:60;;44287:1;44263:21;44257:28;44253:1;44240:11;44227;44220:35;44213:76;44198:91;;44388:1;44375:11;44353:19;44347:26;44340:50;44316:22;44309:82;44463:1;44459:2;44438:19;44431:34;44416:13;44409:57;44548:1;44544:2;44521:21;44514:36;44491:21;44484:67;44620:1;44616:2;44596:18;44589:33;44576:11;44569:54;44714:1;44710:2;44680:27;44674:34;44667:49;44648:17;44641:76;44784:1;44780:2;44760:18;44753:33;44742:9;44735:52;;;;;;;;;;;;45299:11;45293:18;45280:31;45347:10;45341:17;45395:11;45389:18;46212:1;46182;46167:12;46161:19;46155:4;46148:36;46140:5;46126:11;46120:18;46116:30;46112:73;46082:1;46067:12;46061:19;46055:4;46048:36;46040:5;46026:11;46020:18;46016:30;46012:73;45979:257;46518:1;46488;46473:12;46467:19;46461:4;46454:36;46446:5;46432:11;46426:18;46422:30;46418:73;46388:1;46373:12;46367:19;46361:4;46354:36;46346:5;46332:11;46326:18;46322:30;46318:73;46285:257;46655:1;46651;46647;46643:2;46639;46632:17;46619:10;46613:17;46606:47;46587:16;46581:23;46574:83;46941:1;46911;46893:15;46887:22;46881:4;46874:39;46866:5;46852:11;46846:18;46842:30;46838:76;46808:1;46790:15;46784:22;46778:4;46771:39;46763:5;46749:11;46743:18;46739:30;46735:76;46702:263;46675:290;;47249:1;47219;47201:15;47195:22;47189:4;47182:39;47174:5;47160:11;47154:18;47150:30;47146:76;47116:1;47098:15;47092:22;47086:4;47079:39;47071:5;47057:11;47051:18;47047:30;47043:76;47010:263;46983:290;;47512:1;47482;47478;47474;47470:2;47466;47459:17;47440:16;47434:23;47427:53;47408:16;47402:23;47395:89;47392:1;47388:97;47355:6;47322:214;47291:245;;47940:1;47926:11;47920:18;47901:16;47895:23;47888:54;47870:16;47863:80;48467:1;48412;48349;48312;48286:22;48280:29;48277:1;48273:37;48254:16;48248:23;48241:73;48196:9;48190:16;48149:232;48101:16;48095:23;48058:382;48025:6;47992:499;47961:530;;48586:1;48572:11;48566:18;48547:16;48541:23;48534:54;48516:16;48509:80;48992:1;48937;48904;48900;48896;48893;48889:9;48876:10;48870:17;48863:39;48849:11;48843:18;48836:70;48788:16;48782:23;48745:220;48712:6;48679:337;48636:20;48607:428;;;;;;49130:1;49116:11;49110:18;49091:16;49085:23;49078:54;49060:16;49053:80;49708:1;49694:11;49688:18;49676:9;49670:16;49663:47;49852:1;49848;49844;49824:17;49818:24;49804:11;49798:18;49791:55;49777:11;49771:18;49764:86;49761:1;49754:100;49728:126;;49905:1;49893:9;49887:16;49884:1;49877:30;49872:35;;50049:1;50045;50041;50021:17;50015:24;50001:11;49995:18;49988:55;49974:11;49968:18;49961:86;49958:1;49951:100;49925:126;;50102:1;50090:9;50084:16;50081:1;50074:30;50069:35;;50246:1;50242;50238;50218:17;50212:24;50198:11;50192:18;50185:55;50171:11;50165:18;50158:86;50155:1;50148:100;50122:126;;50925:1;50882:15;50876:22;50821:1;50788;50776:9;50770:16;50752:15;50746:22;50739:51;50676:1;50639;50623:13;50617:20;50599:15;50593:22;50586:55;50549:1;50532:14;50526:21;50508:15;50502:22;50495:56;50454:254;50417:432;50384:565;51661:1;51612:21;51606:28;51551:1;51518;51506:9;51500:16;51476:21;51470:28;51463:57;51400:1;51363;51347:13;51341:20;51317:21;51311:28;51304:61;51267:1;51250:14;51244:21;51220;51214:28;51207:62;51166:266;51129:450;51096:589;52372:1;52368;52365;52352:10;52346:17;52339:31;52325:11;52319:18;52312:62;52478:1;52464:11;52458:18;52454:1;52432:19;52426:26;52423:1;52416:40;52409:71;52392:88;;52592:1;52571:19;52567:1;52563;52550:10;52544:17;52535:7;52528:37;52525:1;52518:51;52511:83;52498:96;;52650:1;52643:5;52632:9;52625:27;52612:40;;52734:1;52730;52727;52714:10;52708:17;52701:31;52690:9;52683:53;52670:66;;52810:1;52796:11;52790:18;52776:11;52770:18;52763:49;52754:58;;52868:1;52861:5;52850:9;52843:27;52830:40;;52945:1;52925:17;52919:24;52908:9;52901:46;52888:59;;53011:1;53003:5;53000:1;52996:13;52985:9;52978:35;52965:48;;53869:1;53823:19;53794:1;53790;53777:10;53771:17;53752:16;53746:23;53739:53;53726:10;53720:17;53713:83;53680:213;53640:253;;;;53973:1;53961:9;53955:16;53937:15;53931:22;53924:51;54043:1;54035:5;54032:1;54028:13;54015:11;54008:37;53993:52;;54130:1;54104:23;54098:30;54085:11;54078:54;54063:69;;54229:1;54225;54205:17;54199:24;54192:5;54185:42;54172:11;54165:66;54150:81;;;54351:1;54332:16;54326:23;54322:1;54308:11;54305:1;54301:19;54290:9;54283:41;54276:77;54258:16;54251:103;;;54489:1;54470:16;54464:23;54445:16;54439:23;54432:59;54414:16;54407:85;57262:1;57248:11;57242:18;57228:11;57222:18;57215:49;57341:1;57327:11;57321:18;57307:11;57301:18;57294:49;57420:1;57406:11;57400:18;57386:11;57380:18;57373:49;57499:1;57485:11;57479:18;57465:11;57459:18;57452:49;58070:1;58013:30;57958:1;57925;57921;57918;57914:9;57896:15;57890:22;57883:44;57850:1;57836:11;57830:18;57826:1;57812:11;57806:18;57792:11;57786:18;57779:49;57772:80;57735:251;57702:392;58402:1;58398;58394;58390;58386;58378:6;58372:4;58365:23;58359:4;58352:40;58346:4;58339:57;58333:4;58326:74;58312:11;58306:18;58273:153;58236:190;;;;;;59467:1;59412;59349;59278;59274;59260:11;59254:18;59240:11;59234:18;59227:49;59206:17;59200:24;59197:1;59193:32;59148:166;59101:11;59095:18;59054:327;59021:1;59017;59014;59010:9;58992:15;58986:22;58979:44;58942:498;58903:11;58897:18;58864:627;60628:1;60573;60510;60439;60398;60362:34;60342:17;60336:24;60329:71;60288:1;60284;60281;60277:9;60259:15;60253:22;60246:44;60201:274;60158:8;60117:425;60070:15;60064:22;60027:574;59983:16;59977:23;59944:708;59902:19;59873:798;;;60805:1;60787:15;60781:22;60762:16;60756:23;60749:58;60731:16;60724:84;61666:1;61663;61659:9;61712:1;61709;61705:9;61797:1;61782:11;61776:18;61773:1;61769:26;61755:11;61749:18;61742:57;61882:1;61867:11;61861:18;61858:1;61854:26;61840:11;61834:18;61827:57;61967:1;61952:11;61946:18;61943:1;61939:26;61925:11;61919:18;61912:57;62058:1;62043:11;62037:18;62034:1;62030:26;62010:17;62004:24;61997:63;62466:1;62422:16;62416:23;62361:1;62328;62315:11;62311:2;62304:26;62271:1;62267;62256:9;62252:2;62245:24;62241:1;62236:2;62233:1;62229:10;62225:1;62221:2;62217;62210:17;62203:40;62196:77;62159:230;62126:364;62080:410;;63081:1;63026;62993;62979:11;62973:18;62954:16;62948:23;62941:54;62878:1;62841;62828:11;62824:2;62817:26;62780:1;62776;62765:9;62761:2;62754:24;62750:1;62745:2;62742:1;62738:10;62734:1;62730:2;62726;62719:17;62712:40;62705:77;62664:246;62627:427;62583:17;62550:555;62508:597;;63700:1;63645;63612;63594:15;63588:22;63569:16;63563:23;63556:58;63493:1;63456;63443:11;63439:2;63432:26;63395:1;63391;63380:9;63376:2;63369:24;63365:1;63360:2;63357:1;63353:10;63349:1;63345:2;63341;63334:17;63327:40;63320:77;63279:246;63242:431;63198:17;63165:559;63123:601;;64320:1;64265;64232;64213:16;64207:23;64188:16;64182:23;64175:59;64112:1;64075;64062:11;64058:2;64051:26;64014:1;64010;63999:9;63995:2;63988:24;63984:1;63979:2;63976:1;63972:10;63968:1;63964:2;63960;63953:17;63946:40;63939:77;63898:246;63861:432;63817:17;63784:560;63742:602;;;;;64432:1;64415:14;64409:21;64390:17;64383:51;64461:13;64454:40;-1:-1:-1;;64610:16:0;64604:23;64585:16;64579:23;64629:1;;-1:-1:-1;64572:59:0;64554:16;64547:85;65767:1;65730:9;65724:16;65669:1;65636;65622:11;65616:18;65612:1;65598:11;65592:18;65578:11;65572:18;65565:49;65558:80;65525:1;65511:11;65505:18;65490:11;65484:18;65481:1;65477:26;65470:57;65433:264;65400:391;65879:1;65865:11;65859:18;65845:11;65839:18;65832:49;65997:1;65993;65978:11;65972:18;65969:1;65965:26;65951:11;65945:18;65938:57;65923:13;65916:83;65899:100;;66078:1;66062:13;66056:20;66041:13;66034:46;66017:63;;66164:1;66150:11;66144:18;66130:11;66124:18;66117:49;66235:1;66221:11;66215:18;66204:9;66197:40;66184:53;;66610:1;66555;66522;66508:11;66502:18;66488:11;66482:18;66475:49;66442:1;66428:11;66422:18;66408:11;66402:18;66395:49;66358:225;66322:9;66289:345;66255:379;;67116:1;67030;66993;66979:11;66973:18;66959:11;66953:18;66946:49;66909:1;66895:11;66889:18;66875:11;66869:18;66862:49;66821:241;66789:1;66755:334;66719:9;66686:454;66652:488;;67224:1;67210:11;67204:18;67190:11;67184:18;67177:49;67286:1;67275:9;67264;67257:31;67244:44;;67355:1;67343:9;67337:16;67326:9;67319:38;67306:51;;67928:1;67924;67913:9;67902;67895:31;67891:1;67876:13;67865:9;67858:35;67851:79;67833:97;;68006:1;67987:16;67981:23;67969:10;67962:46;67948:60;;68243:1;68214;68200:11;68194:18;68180:11;68174:18;68167:49;68138:1;68126:9;68120:16;68106:11;68100:18;68093:47;68060:207;68026:241;;68580:1;68547;68532:11;68526:18;68523:1;68519:26;68505:11;68499:18;68492:57;68459:1;68447:9;68441:16;68427:11;68421:18;68414:47;68377:231;68349:1;68319:312;68285:346;;68946:1;68917;68913;68898:11;68892:18;68889:1;68885:26;68871:11;68865:18;68858:57;68844:11;68838:18;68831:88;68801:1;68797;68783:11;68777:18;68763:11;68757:18;68750:49;68736:11;68730:18;68723:80;68720:1;68716:88;68683:287;68649:321;;69221:1;69192;69178:11;69172:18;69153:16;69147:23;69140:54;69111:1;69100:9;69096:1;69085:9;69074;69067:31;69060:53;69027:218;68988:257;;;;69444:1;69423:18;69417:25;69413:1;69401:10;69389;69382:33;69375:71;69356:17;69349:98;;;69697:1;69678:16;69672:23;69653:16;69647:23;69640:59;69622:16;69615:85;71601:1;71568;71554:11;71548:18;71528:17;71522:24;71515:55;71482:1;71462:17;71456:24;71442:11;71436:18;71429:55;71392:237;72081:1;72031:17;72025:24;72022:1;72018:32;71955:1;71918;71904:11;71898:18;71884:11;71878:18;71871:49;71834:1;71820:11;71814:18;71800:11;71794:18;71787:49;71746:241;71709:400;72201:1;-1:-1:-1;;;72165:23:0;72158:45;72131:72;;72318:1;72297:17;72291:24;72288:1;72284:32;72259:23;72252:68;72225:95;;72418:1;72401:15;72376:23;72369:51;72342:78;;72521:1;72507:11;72501:18;72476:23;72469:54;72442:81;;72599:1;-1:-1:-1;;;72571:15:0;72564:37;72545:56;;72754:1;72750;72730:17;72724:24;72704:17;72698:24;72691:61;72674:15;72667:89;72623:133;;73036:1;72993:11;72987:18;72954:1;72949;72935:11;72929:18;72915:11;72909:18;72902:49;72899:1;72895:57;72878:15;72871:85;72834:230;73517:1;73474:11;73468:18;73405:1;73367;73347:17;73341:24;73321:17;73315:24;73308:61;73305:1;73301:69;73264:1;73250:11;73244:18;73227:15;73220:46;73179:258;73142:403;73086:459;;73837:1;73794:11;73788:18;73755:1;73730:23;73726:1;73701:23;73676;73669:59;73662:95;73625:240;73896:31;73889:66;-1:-1:-1;;74718:17:0;74712:24;74753:1;;-1:-1:-1;74738:13:0;;74705:50;74852:1;74832:17;74826:24;74806:18;74799:55;74777:77;;74940:1;74925:13;74905:18;74898:44;74876:66;;75033:1;75019:11;75013:18;74993;74986:49;74964:71;;75121:1;75106:13;75086:18;75079:44;75057:66;;75214:1;75200:11;75194:18;75174;75167:49;75145:71;;75302:1;75287:13;75267:18;75260:44;75238:66;;75395:1;75381:11;75375:18;75355;75348:49;75326:71;;75496:1;75481:11;75475:18;75472:1;75468:26;75448:18;75441:57;75419:79;;75589:1;75575:11;75569:18;75549;75542:49;75520:71;;76363:1;76348:13;76328:17;76322:24;76315:50;76462:1;76442:17;76436:24;76416:18;76409:55;76387:77;;76550:1;76535:13;76515:18;76508:44;76486:66;;76649:1;76629:17;76623:24;76603:18;76596:55;76574:77;;76737:1;76722:13;76702:18;76695:44;76673:66;;76830:1;76816:11;76810:18;76790;76783:49;76761:71;;76918:1;76903:13;76883:18;76876:44;76854:66;;77011:1;76997:11;76991:18;76971;76964:49;76942:71;;77118:1;77097:17;77091:24;77088:1;77084:32;77064:18;77057:63;77035:85;;77211:1;77197:11;77191:18;77171;77164:49;77142:71;;77406:1;77392:11;77386:18;77382:1;77362:18;77342;77335:49;77328:80;77270:31;77237:194;;;78148:1;78136:9;78130:16;78116:11;78110:18;78103:47;78243:1;78229:11;78223:18;78202:19;78195:50;78172:73;;78336:1;78324:9;78318:16;78297:19;78290:48;78267:71;;78431:1;78417:11;78411:18;78390:19;78383:50;78360:73;;78524:1;78512:9;78506:16;78485:19;78478:48;78455:71;;78619:1;78605:11;78599:18;78578:19;78571:50;78548:73;;78673:19;78793:1;78778:11;78772:18;78769:1;78765:26;78744:19;78737:58;78714:81;;78849:19;78826:21;78819:50;79027:1;79012:11;79006:18;79003:1;78999:26;78979:17;78973:24;78966:63;79187:1;79172:11;79166:18;79163:1;79159:26;79139:17;79133:24;79126:63;79399:1;79395;79391;79388;79384:9;79371:11;79364:33;79351:11;79344:57;79668:1;79664;79650:11;79647:1;79643:19;79640:1;79633:33;79619:12;79612:58;79532:138;;80517:1;80467:19;80404:1;80357:11;80351:18;80280:1;80208:33;80167:1;80153:11;80147:18;80098:47;80091:78;80046:270;80005:431;79968:577;79911:30;79878:690;81209:1;81197:9;81191:16;81171:17;81165:24;81158:53;81129:82;;81318:1;81298:17;81292:24;81269:21;81262:58;81237:83;;81419:1;81407:9;81401:16;81378:21;81371:50;81346:75;;81528:1;81508:17;81502:24;81479:21;81472:58;81447:83;;81629:1;81617:9;81611:16;81588:21;81581:50;81556:75;;81746:1;81722:21;81719:1;81715:29;81695:17;81689:24;81682:66;81657:91;;81914:1;81899:11;81893:18;81890:1;81886:26;81866:17;81860:24;81853:63;81834:82;;82453:1;82416;82412;82388:21;82385:1;82381:29;82378:1;82371:43;82358:11;82351:67;82314:1;82300:11;82297:1;82293:19;82290:1;82283:33;82242:243;82122:363;;83583:1;83560:20;83557:1;83553:28;83539:11;83533:18;83526:59;83686:1;83682;83678;83675;83671:9;83658:11;83651:33;83638:11;83631:57;83611:77;;83858:1;83854;83850;83847;83843:9;83820:21;83813:43;83790:21;83783:77;83714:146;;84142:1;84095:11;84089:18;83971:83;83930:244;83886:288;;84262:1;84227:33;84218:7;84211:53;84200:64;;84337:1;84323:11;84317:18;84308:7;84301:38;84290:49;;84426:1;84392:32;84383:7;84376:52;84365:63;;84501:1;84487:11;84481:18;84472:7;84465:38;84454:49;;84570:1;84556:12;84547:7;84540:32;84529:43;;;84639:7;84607:30;84600:47;80592:4078;;84867:1;84852:11;84846:18;84843:1;84839:26;84819:17;84813:24;84806:63;84783:86;;85195:1;85180:11;85174:18;85171:1;85167:26;85163:1;85159;85145:11;85142:1;85138:19;85135:1;85128:33;85111:15;85104:61;85063:164;84998:229;;86055:1;86041:11;86035:18;86002:30;85996:37;85989:68;85966:91;;86216:1;86212;86198:11;86192:18;86162:28;86155:59;86138:15;86131:87;86083:135;;86377:1;86373;86359:11;86353:18;86329:21;86323:28;86316:59;86299:15;86292:87;86244:135;;86468:1;86454:11;86448:18;86431:15;86424:46;86405:65;;86676:1;86672;86654:15;86648:22;86615:30;86609:37;86602:72;86585:15;86544:164;86496:212;;86826:1;86792:31;86786:38;86769:15;86762:66;86736:92;;86943:1;86909:31;86903:38;86883:18;86876:69;86854:91;;87042:1;87026:13;87020:20;87000:18;86993:51;86971:73;;87144:1;87125:16;87119:23;87099:18;87092:54;87070:76;;87195:18;87181:12;87174:40;87365:1;87346:16;87340:23;87321:16;87315:23;87308:59;87290:16;87283:85;84694:2697;;;88786:1;88737:21;88731:28;88676:1;88632:12;88626:19;88563:1;88510:17;88504:24;88433:1;88380:13;88374:20;88295:1;88232:19;88226:26;88181:1;88162:16;88156:23;88133:20;88127:27;88120:63;88071:264;88026:443;87985:610;87948:756;87915:895;87875:17;87846:983;;;88997:13;88991:20;89279:24;89272:51;;;89348:24;89341:58;;;;89210:42;89162:4;89149:18;89210:42;89470:15;89210:42;89430:24;89417:69;-1:-1:-1;;89668:26:0;89642:24;89632:63;89732:17;;;89722:8;89715:35;89841:4;89834:23;;;89889:4;89883;89875:19;89956:1;89949:4;89943;89933:21;89929:29;89919:8;89912:47;89991:4;89985;89977:19;90058:1;90051:4;90045;90035:21;90031:29;90021:8;90014:47;90093:4;90087;90079:19;90160:1;90153:4;90147;90137:21;90133:29;90123:8;90116:47;90195:4;90189;90181:19;90262:1;90255:4;90249;90239:21;90235:29;90225:8;90218:47;90297:4;90291;90283:19;90364:1;90357:4;90351;90341:21;90337:29;90327:8;90320:47;90399:4;90393;90385:19;90466:1;90459:4;90453;90443:21;90439:29;90429:8;90422:47;90501:4;90495;90487:19;90568:1;90561:4;90555;90545:21;90541:29;90531:8;90524:47;90603:4;90597;90589:19;90670:1;90663:4;90657;90647:21;90643:29;90633:8;90626:47;90705:4;90699;90691:19;90772:1;90765:4;90759;90749:21;90745:29;90735:8;90728:47;90807:4;90801;90793:19;90875:1;90868:4;90862;90852:21;90848:29;90837:9;90830:48;90910:4;90904;90896:19;90978:1;90971:4;90965;90955:21;90951:29;90940:9;90933:48;91013:4;91007;90999:19;91081:1;91074:4;91068;91058:21;91054:29;91043:9;91036:48;91116:4;91110;91102:19;91184:1;91177:4;91171;91161:21;91157:29;91146:9;91139:48;91219:4;91213;91205:19;91287:1;91280:4;91274;91264:21;91260:29;91249:9;91242:48;91322:4;91316;91308:19;91390:1;91383:4;91377;91367:21;91363:29;91352:9;91345:48;91425:4;91419;91411:19;91493:1;91486:4;91480;91470:21;91466:29;91455:9;91448:48;91528:4;91522;91514:19;91596:1;91589:4;91583;91573:21;91569:29;91558:9;91551:48;91631:4;91625;91617:19;91699:1;91692:4;91686;91676:21;91672:29;91661:9;91654:48;91734:4;91728;91720:19;91802:1;91795:4;91789;91779:21;91775:29;91764:9;91757:48;91837:4;91831;91823:19;91905:1;91898:4;91892;91882:21;91878:29;91867:9;91860:48;91940:4;91934;91926:19;92008:1;92001:4;91995;91985:21;91981:29;91970:9;91963:48;92043:4;92037;92029:19;92111:1;92104:4;92098;92088:21;92084:29;92073:9;92066:48;92146:4;92140;92132:19;92214:1;92207:4;92201;92191:21;92187:29;92176:9;92169:48;92249:4;92243;92235:19;92317:1;92310:4;92304;92294:21;92290:29;92279:9;92272:48;92352:4;92346;92338:19;92420:1;92413:4;92407;92397:21;92393:29;92382:9;92375:48;92455:4;92449;92441:19;92523:1;92516:4;92510;92500:21;92496:29;92485:9;92478:48;92558:4;92552;92544:19;92626:1;92619:4;92613;92603:21;92599:29;92588:9;92581:48;92661:4;92655;92647:19;92729:1;92722:4;92716;92706:21;92702:29;92691:9;92684:48;92764:4;92758;92750:19;92832:1;92825:4;92819;92809:21;92805:29;92794:9;92787:48;93006:4;93000;92992:19;-1:-1:-1;93058:4:0;93052;93042:21;;;93099:17;;;93088:9;93081:36;93167:23;;93227:10;93221:17;-1:-1:-1;93208:31:0;-1:-1:-1;93270:17:0;93264:4;93257:31;93325:16;93319:23;93313:4;93306:37;93380:16;93374:23;93368:4;93361:37;93454:4;93438:21;;93434:29;;;93425:7;93418:46;93587:8;93581:15;93629:8;93623:15;93679:1;93581:15;;93666;93796:1;93793;93789;93785:2;93782:1;93775:16;93768:30;93764:1;93761;93758;93751:15;93748:51;93737:62;;;93843:1;93824:17;93817:28;93900:1;93893:4;93874:17;93870:28;93863:39;;;93993:8;93987:15;94045:8;94039:15;94105:1;94102;94099;94092:15;94235:1;94232;94228;94224:2;94221:1;94214:16;94207:30;94203:1;94200;94197;94190:15;94187:51;94178:7;94174:65;94163:76;;;94270:1;94264:4;94257:15;94303:1;94297:4;94290:15;;;94353:14;94347:21;94341:4;94334:35;94504:4;94484:18;94478:4;94472;94469:1;94462:5;94451:58;94438:72;94664:4;94645:17;94639:4;94645:17;94617:1;94610:5;94599:70;94590:7;94586:84;94575:95;;94748:8;94742:15;94790:8;94784:15;94840:1;94837;94834;94827:15;94970:1;94967;94963;94959:2;94956:1;94949:16;94942:30;94938:1;94935;94932;94925:15;94922:51;94913:7;94909:65;94898:76;;;95005:1;94999:4;94992:15;95038:1;95032:4;95025:15;;;95135:1;95118:14;95112:21;95095:14;95089:21;95082:55;95076:4;95069:69;95276:4;95256:18;95250:4;95244;95241:1;95234:5;95223:58;95210:72;95443:4;95424:17;95418:4;95424:17;95396:1;95389:5;95378:70;95369:7;95365:84;95354:95;;95527:8;95521:15;95569:8;95563:15;95619:1;95616;95613;95606:15;95749:1;95746;95742;95738:2;95735:1;95728:16;95721:30;95717:1;95714;95711;95704:15;95701:51;95692:7;95688:65;95677:76;;;95784:1;95778:4;95771:15;95817:1;95811:4;95804:15;;;95948:1;95931:14;95925:21;95921:1;95904:14;95898:21;95881:14;95875:21;95868:55;95861:89;95855:4;95848:103;96089:4;96069:18;96063:4;96057;96054:1;96047:5;96036:58;96023:72;96256:4;96237:17;96231:4;96237:17;96209:1;96202:5;96191:70;96182:7;96178:84;96167:95;;96340:8;96334:15;96382:8;96376:15;96432:1;96429;96426;96419:15;96562:1;96559;96555;96551:2;96548:1;96541:16;96534:30;96530:1;96527;96524;96517:15;96514:51;96505:7;96501:65;96490:76;;;96597:1;96591:4;96584:15;96630:1;96624:4;96617:15;;;96730:1;96719:8;96713:15;96709:1;96704:3;96694:7;96688:14;96681:30;96674:58;96668:4;96661:72;96872:4;96852:18;96846:4;96840;96837:1;96830:5;96819:58;96806:72;97039:4;97020:17;97014:4;97020:17;96992:1;96985:5;96974:70;96965:7;96961:84;96950:95;;97123:8;97117:15;97165:8;97159:15;97215:1;97212;97209;97202:15;97345:1;97342;97338;97334:2;97331:1;97324:16;97317:30;97313:1;97310;97307;97300:15;97297:51;97288:7;97284:65;97273:76;;;97380:1;97374:4;97367:15;97413:1;97407:4;97400:15;;;97513:1;97502:8;97496:15;97492:1;97487:3;97477:7;97471:14;97464:30;97457:58;97451:4;97444:72;97655:4;97635:18;97629:4;97623;97620:1;97613:5;97602:58;97589:72;97822:4;97803:17;97797:4;97803:17;97775:1;97768:5;97757:70;97748:7;97744:84;97733:95;;97906:8;97900:15;97948:8;97942:15;97998:1;97995;97992;97985:15;98128:1;98125;98121;98117:2;98114:1;98107:16;98100:30;98096:1;98093;98090;98083:15;98080:51;98071:7;98067:65;98056:76;;;98163:1;98157:4;98150:15;98196:1;98190:4;98183:15;;;98296:1;98285:8;98279:15;98275:1;98270:3;98260:7;98254:14;98247:30;98240:58;98234:4;98227:72;98438:4;98418:18;98412:4;98406;98403:1;98396:5;98385:58;98372:72;98605:4;98586:17;98580:4;98586:17;98558:1;98551:5;98540:70;98531:7;98527:84;98516:95;;98689:8;98683:15;98731:8;98725:15;98781:1;98778;98775;98768:15;98911:1;98908;98904;98900:2;98897:1;98890:16;98883:30;98879:1;98876;98873;98866:15;98863:51;98854:7;98850:65;98839:76;;;98946:1;98940:4;98933:15;98979:1;98973:4;98966:15;;;99079:1;99068:8;99062:15;99058:1;99053:3;99043:7;99037:14;99030:30;99023:58;99017:4;99010:72;99221:4;99201:18;99195:4;99189;99186:1;99179:5;99168:58;99155:72;99388:4;99369:17;99363:4;99369:17;99341:1;99334:5;99323:70;99314:7;99310:84;99299:95;;99471:7;99465:14;99512:7;99506:14;99561:1;99558;99555;99548:15;99691:1;99688;99684;99680:2;99677:1;99670:16;99663:30;99659:1;99656;99653;99646:15;99643:51;99634:7;99630:65;99619:76;;;99726:1;99720:4;99713:15;99759:1;99753:4;99746:15;;;99859:1;99848:8;99842:15;99838:1;99833:3;99823:7;99817:14;99810:30;99803:58;99797:4;99790:72;100000:4;99980:18;99974:4;99968;99965:1;99958:5;99947:58;99934:72;100167:4;100148:17;100142:4;100148:17;100120:1;100113:5;100102:70;100093:7;100089:84;100078:95;;100250:7;100244:14;100291:7;100285:14;100340:1;100337;100334;100327:15;100470:1;100467;100463;100459:2;100456:1;100449:16;100442:30;100438:1;100435;100432;100425:15;100422:51;100413:7;100409:65;100398:76;;;100505:1;100499:4;100492:15;100538:1;100532:4;100525:15;;;100638:1;100627:8;100621:15;100617:1;100612:3;100602:7;100596:14;100589:30;100582:58;100576:4;100569:72;100779:4;100759:18;100753:4;100747;100744:1;100737:5;100726:58;100713:72;100946:4;100927:17;100921:4;100927:17;100899:1;100892:5;100881:70;100872:7;100868:84;100857:95;;101036:14;101030:21;101084:14;101078:21;101140:1;101137;101134;101127:15;101270:1;101267;101263;101259:2;101256:1;101249:16;101242:30;101238:1;101235;101232;101225:15;101222:51;101213:7;101209:65;101198:76;;;101305:1;101299:4;101292:15;101338:1;101332:4;101325:15;;;101438:1;101427:8;101421:15;101417:1;101412:3;101402:7;101396:14;101389:30;101382:58;101376:4;101369:72;101586:4;101566:18;101560:4;101554;101551:1;101544:5;101533:58;101520:72;101753:4;101734:17;101728:4;101734:17;101706:1;101699:5;101688:70;101679:7;101675:84;101664:95;;101837:8;101831:15;101879:8;101873:15;101929:1;101926;101923;101916:15;102059:1;102056;102052;102048:2;102045:1;102038:16;102031:30;102027:1;102024;102021;102014:15;102011:51;102002:7;101998:65;101987:76;;;102094:1;102088:4;102081:15;102127:1;102121:4;102114:15;;;102177:8;102171:15;102165:4;102158:29;102318:4;102298:18;102292:4;102286;102283:1;102276:5;102265:58;102252:72;102485:4;102466:17;102460:4;102466:17;102438:1;102431:5;102420:70;102411:7;102407:84;102396:95;;102569:8;102563:15;102611:8;102605:15;102661:1;102658;102655;102648:15;102791:1;102788;102784;102780:2;102777:1;102770:16;102763:30;102759:1;102756;102753;102746:15;102743:51;102734:7;102730:65;102719:76;;;102826:1;102820:4;102813:15;102859:1;102853:4;102846:15;;;102909:8;102903:15;102897:4;102890:29;103050:4;103030:18;103024:4;103018;103015:1;103008:5;102997:58;102984:72;103217:4;103198:17;103192:4;103198:17;103170:1;103163:5;103152:70;103143:7;103139:84;103128:95;;103301:8;103295:15;103343:8;103337:15;103393:1;103390;103387;103380:15;103523:1;103520;103516;103512:2;103509:1;103502:16;103495:30;103491:1;103488;103485;103478:15;103475:51;103466:7;103462:65;103451:76;;;103558:1;103552:4;103545:15;103591:1;103585:4;103578:15;;;103641:8;103635:15;103629:4;103622:29;103782:4;103762:18;103756:4;103750;103747:1;103740:5;103729:58;103716:72;103949:4;103930:17;103924:4;103930:17;103902:1;103895:5;103884:70;103875:7;103871:84;103860:95;;104033:8;104027:15;104075:8;104069:15;104125:1;104122;104119;104112:15;104255:1;104252;104248;104244:2;104241:1;104234:16;104227:30;104223:1;104220;104217;104210:15;104207:51;104198:7;104194:65;104183:76;;;104290:1;104284:4;104277:15;104323:1;104317:4;104310:15;;;104373:9;104367:16;104361:4;104354:30;104516:4;104496:18;104490:4;104484;104481:1;104474:5;104463:58;104450:72;104683:4;104664:17;104658:4;104664:17;104636:1;104629:5;104618:70;104609:7;104605:84;104594:95;;104767:8;104761:15;104809:8;104803:15;104859:1;104856;104853;104846:15;104989:1;104986;104982;104978:2;104975:1;104968:16;104961:30;104957:1;104954;104951;104944:15;104941:51;104932:7;104928:65;104917:76;;;105024:1;105018:4;105011:15;105057:1;105051:4;105044:15;;;105107:9;105101:16;105095:4;105088:30;105250:4;105230:18;105224:4;105218;105215:1;105208:5;105197:58;105184:72;105417:4;105398:17;105392:4;105398:17;105370:1;105363:5;105352:70;105343:7;105339:84;105328:95;;105501:8;105495:15;105543:8;105537:15;105593:1;105590;105587;105580:15;105723:1;105720;105716;105712:2;105709:1;105702:16;105695:30;105691:1;105688;105685;105678:15;105675:51;105666:7;105662:65;105651:76;;;105758:1;105752:4;105745:15;105791:1;105785:4;105778:15;;;105841:9;105835:16;105829:4;105822:30;105984:4;105964:18;105958:4;105952;105949:1;105942:5;105931:58;105918:72;106151:4;106132:17;106126:4;106132:17;106104:1;106097:5;106086:70;106077:7;106073:84;106062:95;;106239:12;106233:19;106285:12;106279:19;106339:1;106336;106333;106326:15;106469:1;106466;106462;106458:2;106455:1;106448:16;106441:30;106437:1;106434;106431;106424:15;106421:51;106412:7;106408:65;106397:76;;;106504:1;106498:4;106491:15;106537:1;106531:4;106524:15;;;106587:9;106581:16;106575:4;106568:30;106734:4;106714:18;106708:4;106702;106699:1;106692:5;106681:58;106668:72;106901:4;106882:17;106876:4;106882:17;106854:1;106847:5;106836:70;106827:7;106823:84;106812:95;;106988:11;106982:18;107033:11;107027:18;107086:1;107083;107080;107073:15;107216:1;107213;107209;107205:2;107202:1;107195:16;107188:30;107184:1;107181;107178;107171:15;107168:51;107159:7;107155:65;107144:76;;;107251:1;107245:4;107238:15;107284:1;107278:4;107271:15;;;107334:9;107328:16;107322:4;107315:30;107480:4;107460:18;107454:4;107448;107445:1;107438:5;107427:58;107414:72;107647:4;107628:17;107622:4;107628:17;107600:1;107593:5;107582:70;107573:7;107569:84;107558:95;;107738:15;107732:22;107787:15;107781:22;107844:1;107841;107838;107831:15;107974:1;107971;107967;107963:2;107960:1;107953:16;107946:30;107942:1;107939;107936;107929:15;107926:51;107917:7;107913:65;107902:76;;;108009:1;108003:4;107996:15;108042:1;108036:4;108029:15;;;108092:9;108086:16;108080:4;108073:30;108242:4;108222:18;108216:4;108210;108207:1;108200:5;108189:58;108176:72;108409:4;108390:17;108384:4;108390:17;108362:1;108355:5;108344:70;108335:7;108331:84;108320:95;;108495:10;108489:17;108539:10;108533:17;108591:1;108588;108585;108578:15;108721:1;108718;108714;108710:2;108707:1;108700:16;108693:30;108689:1;108686;108683;108676:15;108673:51;108664:7;108660:65;108649:76;;;108756:1;108750:4;108743:15;108789:1;108783:4;108776:15;;;108839:9;108833:16;108827:4;108820:30;108985:4;108965:18;108959:4;108953;108950:1;108943:5;108932:58;108919:72;109152:4;109133:17;109127:4;109133:17;109105:1;109098:5;109087:70;109078:7;109074:84;109063:95;;109240:12;109234:19;109286:12;109280:19;109340:1;109337;109334;109327:15;109470:1;109467;109463;109459:2;109456:1;109449:16;109442:30;109438:1;109435;109432;109425:15;109422:51;109413:7;109409:65;109398:76;;;109505:1;109499:4;109492:15;109538:1;109532:4;109525:15;;;109588:9;109582:16;109576:4;109569:30;109735:4;109715:18;109709:4;109703;109700:1;109693:5;109682:58;109669:72;109902:4;109883:17;109877:4;109883:17;109855:1;109848:5;109837:70;109828:7;109824:84;109813:95;;109990:12;109984:19;110036:12;110030:19;110090:1;110087;110084;110077:15;110220:1;110217;110213;110209:2;110206:1;110199:16;110192:30;110188:1;110185;110182;110175:15;110172:51;110163:7;110159:65;110148:76;;;110255:1;110249:4;110242:15;110288:1;110282:4;110275:15;;;110338:9;110332:16;110326:4;110319:30;110485:4;110465:18;110459:4;110453;110450:1;110443:5;110432:58;110419:72;110652:4;110633:17;110627:4;110633:17;110605:1;110598:5;110587:70;110578:7;110574:84;110563:95;;110740:12;110734:19;110786:12;110780:19;110840:1;110837;110834;110827:15;110970:1;110967;110963;110959:2;110956:1;110949:16;110942:30;110938:1;110935;110932;110925:15;110922:51;110913:7;110909:65;110898:76;;;111005:1;110999:4;110992:15;111038:1;111032:4;111025:15;;;111088:9;111082:16;111076:4;111069:30;111235:4;111215:18;111209:4;111203;111200:1;111193:5;111182:58;111169:72;111402:4;111383:17;111377:4;111383:17;111355:1;111348:5;111337:70;111328:7;111324:84;111313:95;;111490:12;111484:19;111536:12;111530:19;111590:1;111587;111584;111577:15;111720:1;111717;111713;111709:2;111706:1;111699:16;111692:30;111688:1;111685;111682;111675:15;111672:51;111663:7;111659:65;111648:76;;;111755:1;111749:4;111742:15;111788:1;111782:4;111775:15;;;111838:9;111832:16;111826:4;111819:30;111985:4;111965:18;111959:4;111953;111950:1;111943:5;111932:58;111919:72;112152:4;112133:17;112127:4;112133:17;112105:1;112098:5;112087:70;112078:7;112074:84;112063:95;;112240:12;112234:19;112286:12;112280:19;112340:1;112337;112334;112327:15;112470:1;112467;112463;112459:2;112456:1;112449:16;112442:30;112438:1;112435;112432;112425:15;112422:51;112413:7;112409:65;112398:76;;;112505:1;112499:4;112492:15;112538:1;112532:4;112525:15;;;112639:1;112627:9;112621:16;112617:1;112612:3;112602:7;112596:14;112589:30;112582:59;112576:4;112569:73;112776:4;112756:18;112750:4;112744;112741:1;112734:5;112723:58;112710:72;112943:4;112924:17;112918:4;112924:17;112896:1;112889:5;112878:70;112869:7;112865:84;112854:95;;113031:12;113025:19;113077:12;113071:19;113131:1;113128;113125;113118:15;113261:1;113258;113254;113250:2;113247:1;113240:16;113233:30;113229:1;113226;113223;113216:15;113213:51;113204:7;113200:65;113189:76;;;113296:1;113290:4;113283:15;113329:1;113323:4;113316:15;;;113430:1;113418:9;113412:16;113408:1;113403:3;113393:7;113387:14;113380:30;113373:59;113367:4;113360:73;113567:4;113547:18;113541:4;113535;113532:1;113525:5;113514:58;113501:72;113734:4;113715:17;113709:4;113715:17;113687:1;113680:5;113669:70;113660:7;113656:84;113645:95;;113822:12;113816:19;113868:12;113862:19;113922:1;113919;113916;113909:15;114052:1;114049;114045;114041:2;114038:1;114031:16;114024:30;114020:1;114017;114014;114007:15;114004:51;113995:7;113991:65;113980:76;;;114087:1;114081:4;114074:15;114120:1;114114:4;114107:15;;;114221:1;114209:9;114203:16;114199:1;114194:3;114184:7;114178:14;114171:30;114164:59;114158:4;114151:73;114358:4;114338:18;114332:4;114326;114323:1;114316:5;114305:58;114292:72;114525:4;114506:17;114500:4;114506:17;114478:1;114471:5;114460:70;114451:7;114447:84;114436:95;;114613:12;114607:19;114659:12;114653:19;114713:1;114710;114707;114700:15;114843:1;114840;114836;114832:2;114829:1;114822:16;114815:30;114811:1;114808;114805;114798:15;114795:51;114786:7;114782:65;114771:76;;;114878:1;114872:4;114865:15;114911:1;114905:4;114898:15;;;115012:1;115000:9;114994:16;114990:1;114985:3;114975:7;114969:14;114962:30;114955:59;114949:4;114942:73;115149:4;115129:18;115123:4;115117;115114:1;115107:5;115096:58;115083:72;115316:4;115297:17;115291:4;115297:17;115269:1;115262:5;115251:70;115242:7;115238:84;115227:95;;115408:16;115402:23;115458:16;115452:23;115516:1;115513;115510;115503:15;115646:1;115643;115639;115635:2;115632:1;115625:16;115618:30;115614:1;115611;115608;115601:15;115598:51;115589:7;115585:65;115574:76;;;115681:1;115675:4;115668:15;115714:1;115708:4;115701:15;;;115764:9;115758:16;115752:4;115745:30;115914:4;115894:18;115888:4;115882;115879:1;115872:5;115861:58;115848:72;116081:4;116062:17;116056:4;116062:17;116034:1;116027:5;116016:70;116007:7;116003:84;115992:95;;116166:9;116160:16;116209:9;116203:16;116260:1;116257;116254;116247:15;116390:1;116387;116383;116379:2;116376:1;116369:16;116362:30;116358:1;116355;116352;116345:15;116342:51;116333:7;116329:65;116318:76;;;116425:1;116419:4;116412:15;116458:1;116452:4;116445:15;;;116508:9;116502:16;116496:4;116489:30;116652:4;116632:18;116626:4;116620;116617:1;116610:5;116599:58;116586:72;116819:4;116800:17;116794:4;116800:17;116772:1;116765:5;116754:70;116745:7;116741:84;116730:95;;116904:9;116898:16;116947:9;116941:16;116998:1;116995;116992;116985:15;117128:1;117125;117121;117117:2;117114:1;117107:16;117100:30;117096:1;117093;117090;117083:15;117080:51;117071:7;117067:65;117056:76;;;117163:1;117157:4;117150:15;117196:1;117190:4;117183:15;;;117246:9;117240:16;117234:4;117227:30;117390:4;117370:18;117364:4;117358;117355:1;117348:5;117337:58;117324:72;117557:4;117538:17;117532:4;117538:17;117510:1;117503:5;117492:70;117483:7;117479:84;117468:95;;117642:9;117636:16;117685:9;117679:16;117736:1;117733;117730;117723:15;117866:1;117863;117859;117855:2;117852:1;117845:16;117838:30;117834:1;117831;117828;117821:15;117818:51;117809:7;117805:65;117794:76;;;117901:1;117895:4;117888:15;117934:1;117928:4;117921:15;;;117984:9;117978:16;117972:4;117965:30;118128:4;118108:18;118102:4;118096;118093:1;118086:5;118075:58;118062:72;118295:4;118276:17;118270:4;118276:17;118248:1;118241:5;118230:70;118221:7;118217:84;118206:95;;118380:9;118374:16;118423:9;118417:16;118474:1;118471;118468;118461:15;118604:1;118601;118597;118593:2;118590:1;118583:16;118576:30;118572:1;118569;118566;118559:15;118556:51;118547:7;118543:65;118532:76;;;118639:1;118633:4;118626:15;118672:1;118666:4;118659:15;;;118722:9;118716:16;118710:4;118703:30;118866:4;118846:18;118840:4;118834;118831:1;118824:5;118813:58;118800:72;119033:4;119014:17;119008:4;119014:17;118986:1;118979:5;118968:70;118959:7;118955:84;118944:95;;119958:1;119929;119915:11;119909:18;119905:1;119895:7;119889:14;119869:17;119863:24;119856:51;119849:82;119813:8;119807:15;119774:208;120368:1;120313;120280;120266:11;120260:18;120256:1;120246:7;120240:14;120220:17;120214:24;120207:51;120200:82;120160:8;120154:15;120117:224;120074:16;120041:351;120000:392;;120778:1;120723;120690;120676:11;120670:18;120666:1;120656:7;120650:14;120630:17;120624:24;120617:51;120610:82;120570:8;120564:15;120527:224;120484:16;120451:351;120410:392;;121188:1;121133;121100;121086:11;121080:18;121076:1;121066:7;121060:14;121040:17;121034:24;121027:51;121020:82;120980:8;120974:15;120937:224;120894:16;120861:351;120820:392;;121596:1;121541;121508;121495:10;121489:17;121485:1;121475:7;121469:14;121450:16;121444:23;121437:50;121430:80;121390:8;121384:15;121347:222;121304:16;121271:349;121230:390;;122004:1;121949;121916;121903:10;121897:17;121893:1;121883:7;121877:14;121858:16;121852:23;121845:50;121838:80;121798:8;121792:15;121755:222;121712:16;121679:349;121638:390;;122426:1;122371;122338;122318:17;122312:24;122308:1;122298:7;122292:14;122266:23;122260:30;122253:57;122246:94;122206:8;122200:15;122163:236;122120:16;122087:363;122046:404;;123418:1;123414;123400:11;123394:18;123383:8;123377:15;123370:46;123352:16;123345:75;123325:95;;123531:1;123527;123513:11;123507:18;123496:8;123490:15;123483:46;123465:16;123458:75;123438:95;;123644:1;123640;123626:11;123620:18;123609:8;123603:15;123596:46;123578:16;123571:75;123551:95;;123758:1;123754;123740:11;123734:18;123722:9;123716:16;123709:47;123691:16;123684:76;123664:96;;123872:1;123868;123854:11;123848:18;123836:9;123830:16;123823:47;123805:16;123798:76;123778:96;;123986:1;123982;123968:11;123962:18;123950:9;123944:16;123937:47;123919:16;123912:76;123892:96;;124104:1;124100;124082:15;124076:22;124064:9;124058:16;124051:51;124033:16;124026:80;124006:100;;124221:1;124217;124200:14;124194:21;124182:9;124176:16;124169:50;124151:16;124144:79;124124:99;;124342:1;124338;124317:18;124311:25;124299:9;124293:16;124286:54;124268:16;124261:83;124241:103;;124458:1;124454;124438:13;124432:20;124420:9;124414:16;124407:49;124389:16;124382:78;124362:98;;124576:1;124572;124554:15;124548:22;124536:9;124530:16;124523:51;124505:16;124498:80;124478:100;;124694:1;124690;124672:15;124666:22;124654:9;124648:16;124641:51;124623:16;124616:80;124596:100;;124812:1;124808;124790:15;124784:22;124772:9;124766:16;124759:51;124741:16;124734:80;124714:100;;124930:1;124926;124908:15;124902:22;124890:9;124884:16;124877:51;124859:16;124852:80;124832:100;;126007:1;125952;125919;125901:15;125895:22;125891:1;125881:7;125875:14;125851:21;125845:28;125838:55;125831:90;125790:9;125784:16;125747:233;125704:16;125671:360;125630:401;;126426:1;126371;126338;126320:15;126314:22;126310:1;126300:7;126294:14;126270:21;126264:28;126257:55;126250:90;126209:9;126203:16;126166:233;126123:16;126090:360;126049:401;;126845:1;126790;126757;126739:15;126733:22;126729:1;126719:7;126713:14;126689:21;126683:28;126676:55;126669:90;126628:9;126622:16;126585:233;126542:16;126509:360;126468:401;;127264:1;127209;127176;127158:15;127152:22;127148:1;127138:7;127132:14;127108:21;127102:28;127095:55;127088:90;127047:9;127041:16;127004:233;126961:16;126928:360;126887:401;;127408:1;127404;127382:19;127376:26;127364:9;127358:16;127351:55;127333:16;127326:84;127306:104;;127523:1;127519;127504:12;127498:19;127486:9;127480:16;127473:48;127455:16;127448:77;127428:97;;127638:1;127634;127619:12;127613:19;127601:9;127595:16;127588:48;127570:16;127563:77;127543:97;;127753:1;127749;127734:12;127728:19;127716:9;127710:16;127703:48;127685:16;127678:77;127658:97;;127868:1;127864;127849:12;127843:19;127831:9;127825:16;127818:48;127800:16;127793:77;127773:97;;127959:1;127939:17;127933:24;127915:16;127908:53;127888:73;;127994:4;127988;127981:18;128039:4;128033;128026:18;128091:16;128088:1;128084:24;128078:4;128071:38;;128264:4;128244:18;128238:4;128232;128229:1;128222:5;128211:58;128198:72;128439:4;128420:17;128414:4;128420:17;128392:1;128385:5;128374:70;128361:84;128472:31;128465:48;;;128653:7;128647:14;128697:10;128691:17;128798:10;128792:17;128846:10;128840:17;128902:1;128792:17;;128889:15;129027:1;129024;129020;129016:2;129013:1;129006:16;128999:30;128995:1;128992;128989;128982:15;128979:51;128968:62;;;129065:1;129059:4;129052:15;129102:1;129096:4;129089:15;;;129219:4;129213;129206:18;129319:4;129299:18;129293:4;129287;129284:1;129277:5;129266:58;129257:7;129253:72;129242:83;;129494:4;129475:17;129469:4;129450:17;129447:1;129440:5;129429:70;129420:7;129416:84;129405:95;;129598:16;129592:23;129652:16;129646:23;129714:1;129711;129708;129701:15;129852:1;129849;129845;129841:2;129838:1;129831:16;129824:30;129820:1;129817;129814;129807:15;129804:51;129795:7;129791:65;129780:76;;;129891:1;129885:4;129878:15;129928:1;129922:4;129915:15;;;130025:1;130013:9;130007:16;130003:1;129997:4;129994:1;129987:18;129980:47;129974:4;129967:61;;130185:4;130165:18;130159:4;130153;130150:1;130143:5;130132:58;130123:7;130119:72;130108:83;;130360:4;130341:17;130335:4;130316:17;130313:1;130306:5;130295:70;130286:7;130282:84;130271:95;;130405:10;130399:17;130393:4;130386:31;130454:10;130448:17;130442:4;130435:31;130503:16;130497:23;130491:4;130484:37;130558:16;130552:23;130546:4;130539:37;130607:1;130601:4;130594:15;130690:4;130684;130678;130672;130669:1;130662:5;130651:44;130642:7;130638:58;130627:69;;130850:4;130831:17;130825:4;130819;130816:1;130809:5;130798:57;130789:7;130785:71;130774:82;;130957:17;130951:24;130948:1;130944:32;130925:17;130918:59;131006:28;131000:35;130997:2072;;;131147:18;131141:25;131207:18;131201:25;131275:1;131272;131269;131262:15;131421:1;131418;131414;131410:2;131407:1;131400:16;131393:30;131389:1;131386;131383;131376:15;131373:51;131364:7;131360:65;131349:76;;;131464:1;131458:4;131451:15;131505:1;131499:4;131492:15;;;131651:1;131648;131645;131638:15;131632:4;131625:29;131739:4;131733;131727;131721;131718:1;131711:5;131700:44;131691:7;131687:58;131676:69;;131855:18;131849:25;131915:18;131909:25;131983:1;131980;131977;131970:15;132129:1;132126;132122;132118:2;132115:1;132108:16;132101:30;132097:1;132094;132091;132084:15;132081:51;132072:7;132068:65;132057:76;;;132172:1;132166:4;132159:15;132213:1;132207:4;132200:15;;;132442:4;132436;132430;132424;132421:1;132414:5;132403:44;132394:7;132390:58;132379:69;;132566:17;132560:24;132554:4;132547:38;132626:17;132620:24;132614:4;132607:38;132743:4;132724:17;132718:4;132712;132709:1;132702:5;132691:57;132682:7;132678:71;132667:82;;132867:17;132861:24;132855:4;132848:38;132927:17;132921:24;132915:4;132908:38;133044:4;133025:17;133019:4;133013;133010:1;133003:5;132992:57;132983:7;132979:71;132968:82;;130997:2072;;133099:7;133089:144;;-1:-1:-1;;;133138:3:0;133131:43;133209:4;133203;133196:18;133089:144;133289:7;133258:29;133251:46;133518:17;133512:24;133506:4;133499:38;133574:17;133568:24;133562:4;133555:38;133624:66;133618:4;133611:80;133739:66;133733:4;133726:80;133837:66;133831:4;133824:80;133935:66;133929:4;133922:80;134041:17;134035:24;134029:4;134022:38;134097:17;134091:24;134085:4;134078:38;134154:10;134148:17;134141:5;134134:32;134204:10;134198:17;134191:5;134184:32;134254:10;134248:17;134241:5;134234:32;134304:10;134298:17;134291:5;134284:32;134387:4;134381;134374:5;134368:4;134365:1;134358:5;134347:45;134336:56;;134439:7;134417:20;134410:37;134491:4;134485:11;134472;134465:32;133394:1118;;;134704:31;134698:38;134644:29;134638:36;134623:11;134617:18;134594:20;134588:27;134584:52;134580:95;134554:201;134526:350;;-1:-1:-1;;;134797:3:0;134790:35;134856:4;134850;134843:18;134526:350;134922:4;134916;134909:18;134958:4;134952;134945:18;196:1081:1;302:6;310;318;326;379:2;367:9;358:7;354:23;350:32;347:52;;;395:1;392;385:12;347:52;435:9;422:23;464:18;505:2;497:6;494:14;491:34;;;521:1;518;511:12;491:34;559:6;548:9;544:22;534:32;;604:7;597:4;593:2;589:13;585:27;575:55;;626:1;623;616:12;575:55;666:2;653:16;692:2;684:6;681:14;678:34;;;708:1;705;698:12;678:34;755:7;748:4;739:6;735:2;731:15;727:26;724:39;721:59;;;776:1;773;766:12;721:59;807:4;799:13;;;;-1:-1:-1;831:6:1;-1:-1:-1;875:20:1;;;862:34;;908:16;;;905:36;;;937:1;934;927:12;905:36;975:8;964:9;960:24;950:34;;1022:7;1015:4;1011:2;1007:13;1003:27;993:55;;1044:1;1041;1034:12;993:55;1086:2;1073:16;1114:2;1104:8;1101:16;1098:36;;;1130:1;1127;1120:12;1098:36;1187:7;1180:4;1168:8;1165:1;1161:16;1157:2;1153:25;1149:36;1146:49;1143:69;;;1208:1;1205;1198:12;1143:69;196:1081;;;;-1:-1:-1;;1239:4:1;1231:13;;-1:-1:-1;;;196:1081:1:o

Swarm Source

ipfs://b574d8b5efd582594a26998fb70c91556aee5a70cd43e2af9a141d70cc906adb

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.