ETH Price: $2,916.58 (+2.65%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60806040173777942023-05-31 8:53:47526 days ago1685523227IN
 Create: Verifier
0 ETH0.1332800927.79762369

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Verifier

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 9999999 runs

Other Settings:
default evmVersion
File 1 of 5 : Verifier.sol
pragma solidity ^0.8.13;

// SPDX-License-Identifier: MIT



import "./Plonk4VerifierWithAccessToDNext.sol";
import "../common/libraries/UncheckedMath.sol";

contract Verifier is Plonk4VerifierWithAccessToDNext {
    using UncheckedMath for uint256;

    function get_verification_key() public pure returns (VerificationKey memory vk) {
        vk.num_inputs = 1;
        vk.domain_size = 67108864;
        vk.omega = PairingsBn254.new_fr(0x1dba8b5bdd64ef6ce29a9039aca3c0e524395c43b9227b96c75090cc6cc7ec97);
        // coefficients
        vk.gate_setup_commitments[0] = PairingsBn254.new_g1(
            0x14c289d746e37aa82ec428491881c4732766492a8bc2e8e3cca2000a40c0ea27,
            0x2f617a7eb9808ad9843d1e080b7cfbf99d61bb1b02076c905f31adb12731bc41
        );
        vk.gate_setup_commitments[1] = PairingsBn254.new_g1(
            0x210b5cc8e6a85d63b65b701b8fb5ad24ff9c41f923432de17fe4ebae04526a8c,
            0x05c10ab17ea731b2b87fb890fa5b10bd3d6832917a616b807a9b640888ebc731
        );
        vk.gate_setup_commitments[2] = PairingsBn254.new_g1(
            0x29d4d14adcfe67a2ac690d6369db6b75e82d8ab3124bc4fa1dd145f41ca6949c,
            0x004f6cd229373f1c1f735ccf49aef6a5c32025bc36c3328596dd0db7d87bef67
        );
        vk.gate_setup_commitments[3] = PairingsBn254.new_g1(
            0x06d15382e8cabae9f98374a9fbdadd424f48e24da7e4c65bf710fd7d7d59a05a,
            0x22e438ad5c51673879ce17073a3d2d29327a97dc3ce61c4f88540e00087695f6
        );
        vk.gate_setup_commitments[4] = PairingsBn254.new_g1(
            0x274a668dfc485cf192d0086f214146d9e02b3040a5a586df344c53c16a87882b,
            0x15f5bb7ad01f162b70fc77c8ea456d67d15a6ce98acbbfd521222810f8ec0a66
        );
        vk.gate_setup_commitments[5] = PairingsBn254.new_g1(
            0x0ba53bf4fb0446927857e33978d02abf45948fc68f4091394ae0827a22cf1e47,
            0x0720d818751ce5b3f11c716e925f60df4679ea90bed516499bdec066f5ff108f
        );
        vk.gate_setup_commitments[6] = PairingsBn254.new_g1(
            0x2e986ba2ea495e5ec6af532980b1dc567f1430bfa82f8de07c12fc097c0e0483,
            0x1555d189f6164e82d78de1b8313c2e923e616b3c8ed0e350c3b61c94516d0b58
        );
        vk.gate_setup_commitments[7] = PairingsBn254.new_g1(
            0x0925959592604ca73c917f9b2e029aa2563c318ddcc5ca29c11badb7b880127b,
            0x2b4a430fcb2fa7d6d67d6c358e01cf0524c7df7e1e56442f65b39bc1a1052367
        );
        // gate selectors
        vk.gate_selectors_commitments[0] = PairingsBn254.new_g1(
            0x28f2a0a95af79ba67e9dd1986bd3190199f661b710a693fc82fb395c126edcbd,
            0x0db75db5de5192d1ba1c24710fc00da16fa8029ac7fe82d855674dcd6d090e05
        );
        vk.gate_selectors_commitments[1] = PairingsBn254.new_g1(
            0x143471a174dfcb2d9cb5ae621e519387bcc93c9dcfc011160b2f5c5f88e32cbe,
            0x2a0194c0224c3d964223a96c4c99e015719bc879125aa0df3f0715d154e71a31
        );
        // permutation
        vk.permutation_commitments[0] = PairingsBn254.new_g1(
            0x1423fa82e00ba22c280181afb12c56eea541933eeb5ec39119b0365b6beab4b9,
            0x0efdcd3423a38f5e2ecf8c7e4fd46f13189f8fed392ad9d8d393e8ba568b06e4
        );
        vk.permutation_commitments[1] = PairingsBn254.new_g1(
            0x0e9b5b12c1090d62224e64aa1696c009aa59a9c3eec458e781fae773e1f4eca5,
            0x1fe3df508c7e9750eb37d9cae5e7437ad11a21fa36530ff821b407b165a79a55
        );
        vk.permutation_commitments[2] = PairingsBn254.new_g1(
            0x25d1a714bd1e258f196e38d6b2826153382c2d04b870d0b7ec250296005129ae,
            0x0883a121b41ca7beaa9de97ecf4417e62aa2eeb9434f24ddacbfed57cbf016a8
        );
        vk.permutation_commitments[3] = PairingsBn254.new_g1(
            0x2f3ede68e854a6b3b14589851cf077a606e2aeb3205c43cc579b7abae39d8f58,
            0x178ccd4b1f78fd79ee248e376b6fc8297d5450900d1e15e8c03e3ed2c171ac8c
        );
        // lookup table commitments
        vk.lookup_selector_commitment = PairingsBn254.new_g1(
            0x1f814e2d87c332e964eeef94ec695eef9d2caaac58b682a43da5107693b06f30,
            0x196d56fb01907e66af9303886fd95328d398e5b2b72906882a9d12c1718e2ee2
        );
        vk.lookup_tables_commitments[0] = PairingsBn254.new_g1(
            0x0ebe0de4a2f39df3b903da484c1641ffdffb77ff87ce4f9508c548659eb22d3c,
            0x12a3209440242d5662729558f1017ed9dcc08fe49a99554dd45f5f15da5e4e0b
        );
        vk.lookup_tables_commitments[1] = PairingsBn254.new_g1(
            0x1b7d54f8065ca63bed0bfbb9280a1011b886d07e0c0a26a66ecc96af68c53bf9,
            0x2c51121fff5b8f58c302f03c74e0cb176ae5a1d1730dec4696eb9cce3fe284ca
        );
        vk.lookup_tables_commitments[2] = PairingsBn254.new_g1(
            0x0138733c5faa9db6d4b8df9748081e38405999e511fb22d40f77cf3aef293c44,
            0x269bee1c1ac28053238f7fe789f1ea2e481742d6d16ae78ed81e87c254af0765
        );
        vk.lookup_tables_commitments[3] = PairingsBn254.new_g1(
            0x1b1be7279d59445065a95f01f16686adfa798ec4f1e6845ffcec9b837e88372e,
            0x057c90cb96d8259238ed86b05f629efd55f472a721efeeb56926e979433e6c0e
        );
        vk.lookup_table_type_commitment = PairingsBn254.new_g1(
            0x2f85df2d6249ccbcc11b91727333cc800459de6ee274f29c657c8d56f6f01563,
            0x088e1df178c47116a69c3c8f6d0c5feb530e2a72493694a623b1cceb7d44a76c
        );
        // non residues
        vk.non_residues[0] = PairingsBn254.new_fr(0x0000000000000000000000000000000000000000000000000000000000000005);
        vk.non_residues[1] = PairingsBn254.new_fr(0x0000000000000000000000000000000000000000000000000000000000000007);
        vk.non_residues[2] = PairingsBn254.new_fr(0x000000000000000000000000000000000000000000000000000000000000000a);

        // g2 elements
        vk.g2_elements[0] = PairingsBn254.new_g2(
            [
                0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2,
                0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed
            ],
            [
                0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b,
                0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa
            ]
        );
        vk.g2_elements[1] = PairingsBn254.new_g2(
            [
                0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1,
                0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0
            ],
            [
                0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4,
                0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55
            ]
        );
    }

    function deserialize_proof(uint256[] calldata public_inputs, uint256[] calldata serialized_proof)
        internal
        pure
        returns (Proof memory proof)
    {
        require(serialized_proof.length == 44);
        proof.input_values = new uint256[](public_inputs.length);
        for (uint256 i = 0; i < public_inputs.length; i = i.uncheckedInc()) {
            proof.input_values[i] = public_inputs[i];
        }

        uint256 j;
        for (uint256 i = 0; i < STATE_WIDTH; i = i.uncheckedInc()) {
            proof.state_polys_commitments[i] = PairingsBn254.new_g1_checked(
                serialized_proof[j],
                serialized_proof[j.uncheckedInc()]
            );

            j = j.uncheckedAdd(2);
        }
        proof.copy_permutation_grand_product_commitment = PairingsBn254.new_g1_checked(
            serialized_proof[j],
            serialized_proof[j.uncheckedInc()]
        );
        j = j.uncheckedAdd(2);

        proof.lookup_s_poly_commitment = PairingsBn254.new_g1_checked(
            serialized_proof[j],
            serialized_proof[j.uncheckedInc()]
        );
        j = j.uncheckedAdd(2);

        proof.lookup_grand_product_commitment = PairingsBn254.new_g1_checked(
            serialized_proof[j],
            serialized_proof[j.uncheckedInc()]
        );
        j = j.uncheckedAdd(2);
        for (uint256 i = 0; i < proof.quotient_poly_parts_commitments.length; i = i.uncheckedInc()) {
            proof.quotient_poly_parts_commitments[i] = PairingsBn254.new_g1_checked(
                serialized_proof[j],
                serialized_proof[j.uncheckedInc()]
            );
            j = j.uncheckedAdd(2);
        }

        for (uint256 i = 0; i < proof.state_polys_openings_at_z.length; i = i.uncheckedInc()) {
            proof.state_polys_openings_at_z[i] = PairingsBn254.new_fr(serialized_proof[j]);

            j = j.uncheckedInc();
        }

        for (uint256 i = 0; i < proof.state_polys_openings_at_z_omega.length; i = i.uncheckedInc()) {
            proof.state_polys_openings_at_z_omega[i] = PairingsBn254.new_fr(serialized_proof[j]);

            j = j.uncheckedInc();
        }
        for (uint256 i = 0; i < proof.gate_selectors_openings_at_z.length; i = i.uncheckedInc()) {
            proof.gate_selectors_openings_at_z[i] = PairingsBn254.new_fr(serialized_proof[j]);

            j = j.uncheckedInc();
        }
        for (uint256 i = 0; i < proof.copy_permutation_polys_openings_at_z.length; i = i.uncheckedInc()) {
            proof.copy_permutation_polys_openings_at_z[i] = PairingsBn254.new_fr(serialized_proof[j]);

            j = j.uncheckedInc();
        }
        proof.copy_permutation_grand_product_opening_at_z_omega = PairingsBn254.new_fr(serialized_proof[j]);

        j = j.uncheckedInc();
        proof.lookup_s_poly_opening_at_z_omega = PairingsBn254.new_fr(serialized_proof[j]);
        j = j.uncheckedInc();
        proof.lookup_grand_product_opening_at_z_omega = PairingsBn254.new_fr(serialized_proof[j]);

        j = j.uncheckedInc();
        proof.lookup_t_poly_opening_at_z = PairingsBn254.new_fr(serialized_proof[j]);

        j = j.uncheckedInc();
        proof.lookup_t_poly_opening_at_z_omega = PairingsBn254.new_fr(serialized_proof[j]);
        j = j.uncheckedInc();
        proof.lookup_selector_poly_opening_at_z = PairingsBn254.new_fr(serialized_proof[j]);
        j = j.uncheckedInc();
        proof.lookup_table_type_poly_opening_at_z = PairingsBn254.new_fr(serialized_proof[j]);
        j = j.uncheckedInc();
        proof.quotient_poly_opening_at_z = PairingsBn254.new_fr(serialized_proof[j]);
        j = j.uncheckedInc();
        proof.linearization_poly_opening_at_z = PairingsBn254.new_fr(serialized_proof[j]);
        j = j.uncheckedInc();
        proof.opening_proof_at_z = PairingsBn254.new_g1_checked(
            serialized_proof[j],
            serialized_proof[j.uncheckedInc()]
        );
        j = j.uncheckedAdd(2);
        proof.opening_proof_at_z_omega = PairingsBn254.new_g1_checked(
            serialized_proof[j],
            serialized_proof[j.uncheckedInc()]
        );
    }

    function verify_serialized_proof(uint256[] calldata public_inputs, uint256[] calldata serialized_proof)
        public
        view
        returns (bool)
    {
        VerificationKey memory vk = get_verification_key();
        require(vk.num_inputs == public_inputs.length);

        Proof memory proof = deserialize_proof(public_inputs, serialized_proof);

        return verify(proof, vk);
    }
}

File 2 of 5 : UncheckedMath.sol
pragma solidity ^0.8.13;

// SPDX-License-Identifier: MIT



library UncheckedMath {
    function uncheckedInc(uint256 _number) internal pure returns (uint256) {
        unchecked {
            return _number + 1;
        }
    }

    function uncheckedAdd(uint256 _lhs, uint256 _rhs) internal pure returns (uint256) {
        unchecked {
            return _lhs + _rhs;
        }
    }
}

File 3 of 5 : Plonk4VerifierWithAccessToDNext.sol
pragma solidity ^0.8.13;

// SPDX-License-Identifier: MIT



import "./libraries/PairingsBn254.sol";
import "./libraries/TranscriptLib.sol";
import "../common/libraries/UncheckedMath.sol";

uint256 constant STATE_WIDTH = 4;
uint256 constant NUM_G2_ELS = 2;

struct VerificationKey {
    uint256 domain_size;
    uint256 num_inputs;
    PairingsBn254.Fr omega;
    PairingsBn254.G1Point[2] gate_selectors_commitments;
    PairingsBn254.G1Point[8] gate_setup_commitments;
    PairingsBn254.G1Point[STATE_WIDTH] permutation_commitments;
    PairingsBn254.G1Point lookup_selector_commitment;
    PairingsBn254.G1Point[4] lookup_tables_commitments;
    PairingsBn254.G1Point lookup_table_type_commitment;
    PairingsBn254.Fr[STATE_WIDTH - 1] non_residues;
    PairingsBn254.G2Point[NUM_G2_ELS] g2_elements;
}

contract Plonk4VerifierWithAccessToDNext {
    using PairingsBn254 for PairingsBn254.G1Point;
    using PairingsBn254 for PairingsBn254.G2Point;
    using PairingsBn254 for PairingsBn254.Fr;

    using TranscriptLib for TranscriptLib.Transcript;

    using UncheckedMath for uint256;

    struct Proof {
        uint256[] input_values;
        // commitments
        PairingsBn254.G1Point[STATE_WIDTH] state_polys_commitments;
        PairingsBn254.G1Point copy_permutation_grand_product_commitment;
        PairingsBn254.G1Point[STATE_WIDTH] quotient_poly_parts_commitments;
        // openings
        PairingsBn254.Fr[STATE_WIDTH] state_polys_openings_at_z;
        PairingsBn254.Fr[1] state_polys_openings_at_z_omega;
        PairingsBn254.Fr[1] gate_selectors_openings_at_z;
        PairingsBn254.Fr[STATE_WIDTH - 1] copy_permutation_polys_openings_at_z;
        PairingsBn254.Fr copy_permutation_grand_product_opening_at_z_omega;
        PairingsBn254.Fr quotient_poly_opening_at_z;
        PairingsBn254.Fr linearization_poly_opening_at_z;
        // lookup commitments
        PairingsBn254.G1Point lookup_s_poly_commitment;
        PairingsBn254.G1Point lookup_grand_product_commitment;
        // lookup openings
        PairingsBn254.Fr lookup_s_poly_opening_at_z_omega;
        PairingsBn254.Fr lookup_grand_product_opening_at_z_omega;
        PairingsBn254.Fr lookup_t_poly_opening_at_z;
        PairingsBn254.Fr lookup_t_poly_opening_at_z_omega;
        PairingsBn254.Fr lookup_selector_poly_opening_at_z;
        PairingsBn254.Fr lookup_table_type_poly_opening_at_z;
        PairingsBn254.G1Point opening_proof_at_z;
        PairingsBn254.G1Point opening_proof_at_z_omega;
    }

    struct PartialVerifierState {
        PairingsBn254.Fr zero;
        PairingsBn254.Fr alpha;
        PairingsBn254.Fr beta;
        PairingsBn254.Fr gamma;
        PairingsBn254.Fr[9] alpha_values;
        PairingsBn254.Fr eta;
        PairingsBn254.Fr beta_lookup;
        PairingsBn254.Fr gamma_lookup;
        PairingsBn254.Fr beta_plus_one;
        PairingsBn254.Fr beta_gamma;
        PairingsBn254.Fr v;
        PairingsBn254.Fr u;
        PairingsBn254.Fr z;
        PairingsBn254.Fr z_omega;
        PairingsBn254.Fr z_minus_last_omega;
        PairingsBn254.Fr l_0_at_z;
        PairingsBn254.Fr l_n_minus_one_at_z;
        PairingsBn254.Fr t;
        PairingsBn254.G1Point tp;
    }

    function evaluate_l0_at_point(uint256 domain_size, PairingsBn254.Fr memory at)
        internal
        view
        returns (PairingsBn254.Fr memory num)
    {
        PairingsBn254.Fr memory one = PairingsBn254.new_fr(1);

        PairingsBn254.Fr memory size_fe = PairingsBn254.new_fr(domain_size);
        PairingsBn254.Fr memory den = at.copy();
        den.sub_assign(one);
        den.mul_assign(size_fe);

        den = den.inverse();

        num = at.pow(domain_size);
        num.sub_assign(one);
        num.mul_assign(den);
    }

    function evaluate_lagrange_poly_out_of_domain(
        uint256 poly_num,
        uint256 domain_size,
        PairingsBn254.Fr memory omega,
        PairingsBn254.Fr memory at
    ) internal view returns (PairingsBn254.Fr memory res) {
        // (omega^i / N) / (X - omega^i) * (X^N - 1)
        require(poly_num < domain_size);
        PairingsBn254.Fr memory one = PairingsBn254.new_fr(1);
        PairingsBn254.Fr memory omega_power = omega.pow(poly_num);
        res = at.pow(domain_size);
        res.sub_assign(one);
        require(res.value != 0); // Vanishing polynomial can not be zero at point `at`
        res.mul_assign(omega_power);

        PairingsBn254.Fr memory den = PairingsBn254.copy(at);
        den.sub_assign(omega_power);
        den.mul_assign(PairingsBn254.new_fr(domain_size));

        den = den.inverse();

        res.mul_assign(den);
    }

    function evaluate_vanishing(uint256 domain_size, PairingsBn254.Fr memory at)
        internal
        view
        returns (PairingsBn254.Fr memory res)
    {
        res = at.pow(domain_size);
        res.sub_assign(PairingsBn254.new_fr(1));
    }

    function initialize_transcript(Proof memory proof, VerificationKey memory vk)
        internal
        pure
        returns (PartialVerifierState memory state)
    {
        TranscriptLib.Transcript memory transcript = TranscriptLib.new_transcript();

        for (uint256 i = 0; i < vk.num_inputs; i = i.uncheckedInc()) {
            transcript.update_with_u256(proof.input_values[i]);
        }

        for (uint256 i = 0; i < STATE_WIDTH; i = i.uncheckedInc()) {
            transcript.update_with_g1(proof.state_polys_commitments[i]);
        }

        state.eta = transcript.get_challenge();
        transcript.update_with_g1(proof.lookup_s_poly_commitment);

        state.beta = transcript.get_challenge();
        state.gamma = transcript.get_challenge();

        transcript.update_with_g1(proof.copy_permutation_grand_product_commitment);
        state.beta_lookup = transcript.get_challenge();
        state.gamma_lookup = transcript.get_challenge();
        transcript.update_with_g1(proof.lookup_grand_product_commitment);
        state.alpha = transcript.get_challenge();

        for (uint256 i = 0; i < proof.quotient_poly_parts_commitments.length; i = i.uncheckedInc()) {
            transcript.update_with_g1(proof.quotient_poly_parts_commitments[i]);
        }
        state.z = transcript.get_challenge();

        transcript.update_with_fr(proof.quotient_poly_opening_at_z);

        for (uint256 i = 0; i < proof.state_polys_openings_at_z.length; i = i.uncheckedInc()) {
            transcript.update_with_fr(proof.state_polys_openings_at_z[i]);
        }

        for (uint256 i = 0; i < proof.state_polys_openings_at_z_omega.length; i = i.uncheckedInc()) {
            transcript.update_with_fr(proof.state_polys_openings_at_z_omega[i]);
        }
        for (uint256 i = 0; i < proof.gate_selectors_openings_at_z.length; i = i.uncheckedInc()) {
            transcript.update_with_fr(proof.gate_selectors_openings_at_z[i]);
        }
        for (uint256 i = 0; i < proof.copy_permutation_polys_openings_at_z.length; i = i.uncheckedInc()) {
            transcript.update_with_fr(proof.copy_permutation_polys_openings_at_z[i]);
        }

        state.z_omega = state.z.copy();
        state.z_omega.mul_assign(vk.omega);

        transcript.update_with_fr(proof.copy_permutation_grand_product_opening_at_z_omega);

        transcript.update_with_fr(proof.lookup_t_poly_opening_at_z);
        transcript.update_with_fr(proof.lookup_selector_poly_opening_at_z);
        transcript.update_with_fr(proof.lookup_table_type_poly_opening_at_z);
        transcript.update_with_fr(proof.lookup_s_poly_opening_at_z_omega);
        transcript.update_with_fr(proof.lookup_grand_product_opening_at_z_omega);
        transcript.update_with_fr(proof.lookup_t_poly_opening_at_z_omega);
        transcript.update_with_fr(proof.linearization_poly_opening_at_z);

        state.v = transcript.get_challenge();

        transcript.update_with_g1(proof.opening_proof_at_z);
        transcript.update_with_g1(proof.opening_proof_at_z_omega);

        state.u = transcript.get_challenge();
    }

    // compute some powers of challenge alpha([alpha^1, .. alpha^8])
    function compute_powers_of_alpha(PartialVerifierState memory state) public pure {
        require(state.alpha.value != 0);
        state.alpha_values[0] = PairingsBn254.new_fr(1);
        state.alpha_values[1] = state.alpha.copy();
        PairingsBn254.Fr memory current_alpha = state.alpha.copy();
        for (uint256 i = 2; i < state.alpha_values.length; i = i.uncheckedInc()) {
            current_alpha.mul_assign(state.alpha);
            state.alpha_values[i] = current_alpha.copy();
        }
    }

    function verify(Proof memory proof, VerificationKey memory vk) internal view returns (bool) {
        // we initialize all challenges beforehand, we can draw each challenge in its own place
        PartialVerifierState memory state = initialize_transcript(proof, vk);
        if (verify_quotient_evaluation(vk, proof, state) == false) {
            return false;
        }
        require(proof.state_polys_openings_at_z_omega.length == 1);

        PairingsBn254.G1Point memory quotient_result = proof.quotient_poly_parts_commitments[0].copy_g1();
        {
            // block scope
            PairingsBn254.Fr memory z_in_domain_size = state.z.pow(vk.domain_size);
            PairingsBn254.Fr memory current_z = z_in_domain_size.copy();
            PairingsBn254.G1Point memory tp;
            // start from i =1
            for (uint256 i = 1; i < proof.quotient_poly_parts_commitments.length; i = i.uncheckedInc()) {
                tp = proof.quotient_poly_parts_commitments[i].copy_g1();
                tp.point_mul_assign(current_z);
                quotient_result.point_add_assign(tp);

                current_z.mul_assign(z_in_domain_size);
            }
        }

        Queries memory queries = prepare_queries(vk, proof, state);
        queries.commitments_at_z[0] = quotient_result;
        queries.values_at_z[0] = proof.quotient_poly_opening_at_z;
        queries.commitments_at_z[1] = aggregated_linearization_commitment(vk, proof, state);
        queries.values_at_z[1] = proof.linearization_poly_opening_at_z;

        require(queries.commitments_at_z.length == queries.values_at_z.length);

        PairingsBn254.G1Point memory aggregated_commitment_at_z = queries.commitments_at_z[0];

        PairingsBn254.Fr memory aggregated_opening_at_z = queries.values_at_z[0];
        PairingsBn254.Fr memory aggregation_challenge = PairingsBn254.new_fr(1);
        PairingsBn254.G1Point memory scaled;
        for (uint256 i = 1; i < queries.commitments_at_z.length; i = i.uncheckedInc()) {
            aggregation_challenge.mul_assign(state.v);
            scaled = queries.commitments_at_z[i].point_mul(aggregation_challenge);
            aggregated_commitment_at_z.point_add_assign(scaled);

            state.t = queries.values_at_z[i];
            state.t.mul_assign(aggregation_challenge);
            aggregated_opening_at_z.add_assign(state.t);
        }

        aggregation_challenge.mul_assign(state.v);

        PairingsBn254.G1Point memory aggregated_commitment_at_z_omega = queries.commitments_at_z_omega[0].point_mul(
            aggregation_challenge
        );
        PairingsBn254.Fr memory aggregated_opening_at_z_omega = queries.values_at_z_omega[0];
        aggregated_opening_at_z_omega.mul_assign(aggregation_challenge);
        for (uint256 i = 1; i < queries.commitments_at_z_omega.length; i = i.uncheckedInc()) {
            aggregation_challenge.mul_assign(state.v);

            scaled = queries.commitments_at_z_omega[i].point_mul(aggregation_challenge);
            aggregated_commitment_at_z_omega.point_add_assign(scaled);

            state.t = queries.values_at_z_omega[i];
            state.t.mul_assign(aggregation_challenge);
            aggregated_opening_at_z_omega.add_assign(state.t);
        }

        return
            final_pairing(
                vk.g2_elements,
                proof,
                state,
                aggregated_commitment_at_z,
                aggregated_commitment_at_z_omega,
                aggregated_opening_at_z,
                aggregated_opening_at_z_omega
            );
    }

    function verify_quotient_evaluation(
        VerificationKey memory vk,
        Proof memory proof,
        PartialVerifierState memory state
    ) internal view returns (bool) {
        uint256[] memory lagrange_poly_numbers = new uint256[](vk.num_inputs);
        for (uint256 i = 0; i < lagrange_poly_numbers.length; i = i.uncheckedInc()) {
            lagrange_poly_numbers[i] = i;
        }
        require(vk.num_inputs > 0);

        PairingsBn254.Fr memory inputs_term = PairingsBn254.new_fr(0);
        for (uint256 i = 0; i < vk.num_inputs; i = i.uncheckedInc()) {
            state.t = evaluate_lagrange_poly_out_of_domain(i, vk.domain_size, vk.omega, state.z);
            state.t.mul_assign(PairingsBn254.new_fr(proof.input_values[i]));
            inputs_term.add_assign(state.t);
        }
        inputs_term.mul_assign(proof.gate_selectors_openings_at_z[0]);
        PairingsBn254.Fr memory result = proof.linearization_poly_opening_at_z.copy();
        result.add_assign(inputs_term);

        // compute powers of alpha
        compute_powers_of_alpha(state);
        PairingsBn254.Fr memory factor = state.alpha_values[4].copy();
        factor.mul_assign(proof.copy_permutation_grand_product_opening_at_z_omega);

        // - alpha_0 * (a + perm(z) * beta + gamma)*()*(d + gamma) * z(z*omega)
        require(proof.copy_permutation_polys_openings_at_z.length == STATE_WIDTH - 1);
        PairingsBn254.Fr memory t; // TMP;
        for (uint256 i = 0; i < proof.copy_permutation_polys_openings_at_z.length; i = i.uncheckedInc()) {
            t = proof.copy_permutation_polys_openings_at_z[i].copy();
            t.mul_assign(state.beta);
            t.add_assign(proof.state_polys_openings_at_z[i]);
            t.add_assign(state.gamma);

            factor.mul_assign(t);
        }

        t = proof.state_polys_openings_at_z[3].copy();
        t.add_assign(state.gamma);
        factor.mul_assign(t);
        result.sub_assign(factor);

        // - L_0(z) * alpha_1
        PairingsBn254.Fr memory l_0_at_z = evaluate_l0_at_point(vk.domain_size, state.z);
        l_0_at_z.mul_assign(state.alpha_values[4 + 1]);
        result.sub_assign(l_0_at_z);

        PairingsBn254.Fr memory lookup_quotient_contrib = lookup_quotient_contribution(vk, proof, state);
        result.add_assign(lookup_quotient_contrib);

        PairingsBn254.Fr memory lhs = proof.quotient_poly_opening_at_z.copy();
        lhs.mul_assign(evaluate_vanishing(vk.domain_size, state.z));
        return lhs.value == result.value;
    }

    function lookup_quotient_contribution(
        VerificationKey memory vk,
        Proof memory proof,
        PartialVerifierState memory state
    ) internal view returns (PairingsBn254.Fr memory result) {
        PairingsBn254.Fr memory t;

        PairingsBn254.Fr memory one = PairingsBn254.new_fr(1);
        state.beta_plus_one = state.beta_lookup.copy();
        state.beta_plus_one.add_assign(one);
        state.beta_gamma = state.beta_plus_one.copy();
        state.beta_gamma.mul_assign(state.gamma_lookup);

        // (s'*beta + gamma)*(zw')*alpha
        t = proof.lookup_s_poly_opening_at_z_omega.copy();
        t.mul_assign(state.beta_lookup);
        t.add_assign(state.beta_gamma);
        t.mul_assign(proof.lookup_grand_product_opening_at_z_omega);
        t.mul_assign(state.alpha_values[6]);

        // (z - omega^{n-1}) for this part
        PairingsBn254.Fr memory last_omega = vk.omega.pow(vk.domain_size - 1);
        state.z_minus_last_omega = state.z.copy();
        state.z_minus_last_omega.sub_assign(last_omega);
        t.mul_assign(state.z_minus_last_omega);
        result.add_assign(t);

        // - alpha_1 * L_{0}(z)
        state.l_0_at_z = evaluate_lagrange_poly_out_of_domain(0, vk.domain_size, vk.omega, state.z);
        t = state.l_0_at_z.copy();
        t.mul_assign(state.alpha_values[6 + 1]);
        result.sub_assign(t);

        // - alpha_2 * beta_gamma_powered L_{n-1}(z)
        PairingsBn254.Fr memory beta_gamma_powered = state.beta_gamma.pow(vk.domain_size - 1);
        state.l_n_minus_one_at_z = evaluate_lagrange_poly_out_of_domain(
            vk.domain_size - 1,
            vk.domain_size,
            vk.omega,
            state.z
        );
        t = state.l_n_minus_one_at_z.copy();
        t.mul_assign(beta_gamma_powered);
        t.mul_assign(state.alpha_values[6 + 2]);

        result.sub_assign(t);
    }

    function aggregated_linearization_commitment(
        VerificationKey memory vk,
        Proof memory proof,
        PartialVerifierState memory state
    ) internal view returns (PairingsBn254.G1Point memory result) {
        // qMain*(Q_a * A + Q_b * B + Q_c * C + Q_d * D + Q_m * A*B + Q_const + Q_dNext * D_next)
        result = PairingsBn254.new_g1(0, 0);
        // Q_a * A
        PairingsBn254.G1Point memory scaled = vk.gate_setup_commitments[0].point_mul(
            proof.state_polys_openings_at_z[0]
        );
        result.point_add_assign(scaled);
        // Q_b * B
        scaled = vk.gate_setup_commitments[1].point_mul(proof.state_polys_openings_at_z[1]);
        result.point_add_assign(scaled);
        // Q_c * C
        scaled = vk.gate_setup_commitments[2].point_mul(proof.state_polys_openings_at_z[2]);
        result.point_add_assign(scaled);
        // Q_d * D
        scaled = vk.gate_setup_commitments[3].point_mul(proof.state_polys_openings_at_z[3]);
        result.point_add_assign(scaled);
        // Q_m* A*B or Q_ab*A*B
        PairingsBn254.Fr memory t = proof.state_polys_openings_at_z[0].copy();
        t.mul_assign(proof.state_polys_openings_at_z[1]);
        scaled = vk.gate_setup_commitments[4].point_mul(t);
        result.point_add_assign(scaled);
        // Q_AC* A*C
        t = proof.state_polys_openings_at_z[0].copy();
        t.mul_assign(proof.state_polys_openings_at_z[2]);
        scaled = vk.gate_setup_commitments[5].point_mul(t);
        result.point_add_assign(scaled);
        // Q_const
        result.point_add_assign(vk.gate_setup_commitments[6]);
        // Q_dNext * D_next
        scaled = vk.gate_setup_commitments[7].point_mul(proof.state_polys_openings_at_z_omega[0]);
        result.point_add_assign(scaled);
        result.point_mul_assign(proof.gate_selectors_openings_at_z[0]);

        PairingsBn254.G1Point
            memory rescue_custom_gate_linearization_contrib = rescue_custom_gate_linearization_contribution(
                vk,
                proof,
                state
            );
        result.point_add_assign(rescue_custom_gate_linearization_contrib);
        require(vk.non_residues.length == STATE_WIDTH - 1);

        PairingsBn254.Fr memory one = PairingsBn254.new_fr(1);
        PairingsBn254.Fr memory factor = state.alpha_values[4].copy();
        for (uint256 i = 0; i < proof.state_polys_openings_at_z.length; ) {
            t = state.z.copy();
            if (i == 0) {
                t.mul_assign(one);
            } else {
                t.mul_assign(vk.non_residues[i - 1]);
            }
            t.mul_assign(state.beta);
            t.add_assign(state.gamma);
            t.add_assign(proof.state_polys_openings_at_z[i]);

            factor.mul_assign(t);
            unchecked {
                ++i;
            }
        }

        scaled = proof.copy_permutation_grand_product_commitment.point_mul(factor);
        result.point_add_assign(scaled);

        // - (a(z) + beta*perm_a + gamma)*()*()*z(z*omega) * beta * perm_d(X)
        factor = state.alpha_values[4].copy();
        factor.mul_assign(state.beta);
        factor.mul_assign(proof.copy_permutation_grand_product_opening_at_z_omega);
        for (uint256 i = 0; i < STATE_WIDTH - 1; i = i.uncheckedInc()) {
            t = proof.copy_permutation_polys_openings_at_z[i].copy();
            t.mul_assign(state.beta);
            t.add_assign(state.gamma);
            t.add_assign(proof.state_polys_openings_at_z[i]);

            factor.mul_assign(t);
        }
        scaled = vk.permutation_commitments[3].point_mul(factor);
        result.point_sub_assign(scaled);

        // + L_0(z) * Z(x)
        state.l_0_at_z = evaluate_lagrange_poly_out_of_domain(0, vk.domain_size, vk.omega, state.z);
        require(state.l_0_at_z.value != 0);
        factor = state.l_0_at_z.copy();
        factor.mul_assign(state.alpha_values[4 + 1]);
        scaled = proof.copy_permutation_grand_product_commitment.point_mul(factor);
        result.point_add_assign(scaled);

        PairingsBn254.G1Point memory lookup_linearization_contrib = lookup_linearization_contribution(proof, state);
        result.point_add_assign(lookup_linearization_contrib);
    }

    function rescue_custom_gate_linearization_contribution(
        VerificationKey memory vk,
        Proof memory proof,
        PartialVerifierState memory state
    ) public view returns (PairingsBn254.G1Point memory result) {
        PairingsBn254.Fr memory t;
        PairingsBn254.Fr memory intermediate_result;

        // a^2 - b = 0
        t = proof.state_polys_openings_at_z[0].copy();
        t.mul_assign(t);
        t.sub_assign(proof.state_polys_openings_at_z[1]);
        // t.mul_assign(challenge1);
        t.mul_assign(state.alpha_values[1]);
        intermediate_result.add_assign(t);

        // b^2 - c = 0
        t = proof.state_polys_openings_at_z[1].copy();
        t.mul_assign(t);
        t.sub_assign(proof.state_polys_openings_at_z[2]);
        t.mul_assign(state.alpha_values[1 + 1]);
        intermediate_result.add_assign(t);

        // c*a - d = 0;
        t = proof.state_polys_openings_at_z[2].copy();
        t.mul_assign(proof.state_polys_openings_at_z[0]);
        t.sub_assign(proof.state_polys_openings_at_z[3]);
        t.mul_assign(state.alpha_values[1 + 2]);
        intermediate_result.add_assign(t);

        result = vk.gate_selectors_commitments[1].point_mul(intermediate_result);
    }

    function lookup_linearization_contribution(Proof memory proof, PartialVerifierState memory state)
        internal
        view
        returns (PairingsBn254.G1Point memory result)
    {
        PairingsBn254.Fr memory zero = PairingsBn254.new_fr(0);

        PairingsBn254.Fr memory t;
        PairingsBn254.Fr memory factor;
        // s(x) from the Z(x*omega)*(\gamma*(1 + \beta) + s(x) + \beta * s(x*omega)))
        factor = proof.lookup_grand_product_opening_at_z_omega.copy();
        factor.mul_assign(state.alpha_values[6]);
        factor.mul_assign(state.z_minus_last_omega);

        PairingsBn254.G1Point memory scaled = proof.lookup_s_poly_commitment.point_mul(factor);
        result.point_add_assign(scaled);

        // Z(x) from - alpha_0 * Z(x) * (\beta + 1) * (\gamma + f(x)) * (\gamma(1 + \beta) + t(x) + \beta * t(x*omega))
        // + alpha_1 * Z(x) * L_{0}(z) + alpha_2 * Z(x) * L_{n-1}(z)

        // accumulate coefficient
        factor = proof.lookup_t_poly_opening_at_z_omega.copy();
        factor.mul_assign(state.beta_lookup);
        factor.add_assign(proof.lookup_t_poly_opening_at_z);
        factor.add_assign(state.beta_gamma);

        // (\gamma + f(x))
        PairingsBn254.Fr memory f_reconstructed;
        PairingsBn254.Fr memory current = PairingsBn254.new_fr(1);
        PairingsBn254.Fr memory tmp0;
        for (uint256 i = 0; i < STATE_WIDTH - 1; i = i.uncheckedInc()) {
            tmp0 = proof.state_polys_openings_at_z[i].copy();
            tmp0.mul_assign(current);
            f_reconstructed.add_assign(tmp0);

            current.mul_assign(state.eta);
        }

        // add type of table
        t = proof.lookup_table_type_poly_opening_at_z.copy();
        t.mul_assign(current);
        f_reconstructed.add_assign(t);

        f_reconstructed.mul_assign(proof.lookup_selector_poly_opening_at_z);
        f_reconstructed.add_assign(state.gamma_lookup);

        // end of (\gamma + f(x)) part
        factor.mul_assign(f_reconstructed);
        factor.mul_assign(state.beta_plus_one);
        t = zero.copy();
        t.sub_assign(factor);
        factor = t;
        factor.mul_assign(state.alpha_values[6]);

        // Multiply by (z - omega^{n-1})
        factor.mul_assign(state.z_minus_last_omega);

        // L_{0}(z) in front of Z(x)
        t = state.l_0_at_z.copy();
        t.mul_assign(state.alpha_values[6 + 1]);
        factor.add_assign(t);

        // L_{n-1}(z) in front of Z(x)
        t = state.l_n_minus_one_at_z.copy();
        t.mul_assign(state.alpha_values[6 + 2]);
        factor.add_assign(t);

        scaled = proof.lookup_grand_product_commitment.point_mul(factor);
        result.point_add_assign(scaled);
    }

    struct Queries {
        PairingsBn254.G1Point[13] commitments_at_z;
        PairingsBn254.Fr[13] values_at_z;
        PairingsBn254.G1Point[6] commitments_at_z_omega;
        PairingsBn254.Fr[6] values_at_z_omega;
    }

    function prepare_queries(
        VerificationKey memory vk,
        Proof memory proof,
        PartialVerifierState memory state
    ) public view returns (Queries memory queries) {
        // we set first two items in calee side so start idx from 2
        uint256 idx = 2;
        for (uint256 i = 0; i < STATE_WIDTH; i = i.uncheckedInc()) {
            queries.commitments_at_z[idx] = proof.state_polys_commitments[i];
            queries.values_at_z[idx] = proof.state_polys_openings_at_z[i];
            idx = idx.uncheckedInc();
        }
        require(proof.gate_selectors_openings_at_z.length == 1);
        queries.commitments_at_z[idx] = vk.gate_selectors_commitments[0];
        queries.values_at_z[idx] = proof.gate_selectors_openings_at_z[0];
        idx = idx.uncheckedInc();
        for (uint256 i = 0; i < STATE_WIDTH - 1; i = i.uncheckedInc()) {
            queries.commitments_at_z[idx] = vk.permutation_commitments[i];
            queries.values_at_z[idx] = proof.copy_permutation_polys_openings_at_z[i];
            idx = idx.uncheckedInc();
        }

        queries.commitments_at_z_omega[0] = proof.copy_permutation_grand_product_commitment;
        queries.commitments_at_z_omega[1] = proof.state_polys_commitments[STATE_WIDTH - 1];

        queries.values_at_z_omega[0] = proof.copy_permutation_grand_product_opening_at_z_omega;
        queries.values_at_z_omega[1] = proof.state_polys_openings_at_z_omega[0];

        PairingsBn254.G1Point memory lookup_t_poly_commitment_aggregated = vk.lookup_tables_commitments[0];
        PairingsBn254.Fr memory current_eta = state.eta.copy();
        for (uint256 i = 1; i < vk.lookup_tables_commitments.length; i = i.uncheckedInc()) {
            state.tp = vk.lookup_tables_commitments[i].point_mul(current_eta);
            lookup_t_poly_commitment_aggregated.point_add_assign(state.tp);

            current_eta.mul_assign(state.eta);
        }
        queries.commitments_at_z[idx] = lookup_t_poly_commitment_aggregated;
        queries.values_at_z[idx] = proof.lookup_t_poly_opening_at_z;
        idx = idx.uncheckedInc();
        queries.commitments_at_z[idx] = vk.lookup_selector_commitment;
        queries.values_at_z[idx] = proof.lookup_selector_poly_opening_at_z;
        idx = idx.uncheckedInc();
        queries.commitments_at_z[idx] = vk.lookup_table_type_commitment;
        queries.values_at_z[idx] = proof.lookup_table_type_poly_opening_at_z;
        queries.commitments_at_z_omega[2] = proof.lookup_s_poly_commitment;
        queries.values_at_z_omega[2] = proof.lookup_s_poly_opening_at_z_omega;
        queries.commitments_at_z_omega[3] = proof.lookup_grand_product_commitment;
        queries.values_at_z_omega[3] = proof.lookup_grand_product_opening_at_z_omega;
        queries.commitments_at_z_omega[4] = lookup_t_poly_commitment_aggregated;
        queries.values_at_z_omega[4] = proof.lookup_t_poly_opening_at_z_omega;
    }

    function final_pairing(
        // VerificationKey memory vk,
        PairingsBn254.G2Point[NUM_G2_ELS] memory g2_elements,
        Proof memory proof,
        PartialVerifierState memory state,
        PairingsBn254.G1Point memory aggregated_commitment_at_z,
        PairingsBn254.G1Point memory aggregated_commitment_at_z_omega,
        PairingsBn254.Fr memory aggregated_opening_at_z,
        PairingsBn254.Fr memory aggregated_opening_at_z_omega
    ) internal view returns (bool) {
        // q(x) = f(x) - f(z) / (x - z)
        // q(x) * (x-z)  = f(x) - f(z)

        // f(x)
        PairingsBn254.G1Point memory pair_with_generator = aggregated_commitment_at_z.copy_g1();
        aggregated_commitment_at_z_omega.point_mul_assign(state.u);
        pair_with_generator.point_add_assign(aggregated_commitment_at_z_omega);

        // - f(z)*g
        PairingsBn254.Fr memory aggregated_value = aggregated_opening_at_z_omega.copy();
        aggregated_value.mul_assign(state.u);
        aggregated_value.add_assign(aggregated_opening_at_z);
        PairingsBn254.G1Point memory tp = PairingsBn254.P1().point_mul(aggregated_value);
        pair_with_generator.point_sub_assign(tp);

        // +z * q(x)
        tp = proof.opening_proof_at_z.point_mul(state.z);
        PairingsBn254.Fr memory t = state.z_omega.copy();
        t.mul_assign(state.u);
        PairingsBn254.G1Point memory t1 = proof.opening_proof_at_z_omega.point_mul(t);
        tp.point_add_assign(t1);
        pair_with_generator.point_add_assign(tp);

        // rhs
        PairingsBn254.G1Point memory pair_with_x = proof.opening_proof_at_z_omega.point_mul(state.u);
        pair_with_x.point_add_assign(proof.opening_proof_at_z);
        pair_with_x.negate();
        // Pairing precompile expects points to be in a `i*x[1] + x[0]` form instead of `x[0] + i*x[1]`
        // so we handle it in code generation step
        PairingsBn254.G2Point memory first_g2 = g2_elements[0];
        PairingsBn254.G2Point memory second_g2 = g2_elements[1];

        return PairingsBn254.pairingProd2(pair_with_generator, first_g2, pair_with_x, second_g2);
    }
}

File 4 of 5 : TranscriptLib.sol
pragma solidity ^0.8.13;

// SPDX-License-Identifier: MIT



import "./PairingsBn254.sol";

library TranscriptLib {
    // flip                    0xe000000000000000000000000000000000000000000000000000000000000000;
    uint256 constant FR_MASK = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    uint32 constant DST_0 = 0;
    uint32 constant DST_1 = 1;
    uint32 constant DST_CHALLENGE = 2;

    struct Transcript {
        bytes32 state_0;
        bytes32 state_1;
        uint32 challenge_counter;
    }

    function new_transcript() internal pure returns (Transcript memory t) {
        t.state_0 = bytes32(0);
        t.state_1 = bytes32(0);
        t.challenge_counter = 0;
    }

    function update_with_u256(Transcript memory self, uint256 value) internal pure {
        bytes32 old_state_0 = self.state_0;
        self.state_0 = keccak256(abi.encodePacked(DST_0, old_state_0, self.state_1, value));
        self.state_1 = keccak256(abi.encodePacked(DST_1, old_state_0, self.state_1, value));
    }

    function update_with_fr(Transcript memory self, PairingsBn254.Fr memory value) internal pure {
        update_with_u256(self, value.value);
    }

    function update_with_g1(Transcript memory self, PairingsBn254.G1Point memory p) internal pure {
        update_with_u256(self, p.X);
        update_with_u256(self, p.Y);
    }

    function get_challenge(Transcript memory self) internal pure returns (PairingsBn254.Fr memory challenge) {
        bytes32 query = keccak256(abi.encodePacked(DST_CHALLENGE, self.state_0, self.state_1, self.challenge_counter));
        self.challenge_counter += 1;
        challenge = PairingsBn254.Fr({value: uint256(query) & FR_MASK});
    }
}

File 5 of 5 : PairingsBn254.sol
pragma solidity ^0.8.13;

// SPDX-License-Identifier: MIT



library PairingsBn254 {
    uint256 constant q_mod = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    uint256 constant r_mod = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
    uint256 constant bn254_b_coeff = 3;

    struct G1Point {
        uint256 X;
        uint256 Y;
    }

    struct Fr {
        uint256 value;
    }

    function new_fr(uint256 fr) internal pure returns (Fr memory) {
        require(fr < r_mod);
        return Fr({value: fr});
    }

    function copy(Fr memory self) internal pure returns (Fr memory n) {
        n.value = self.value;
    }

    function assign(Fr memory self, Fr memory other) internal pure {
        self.value = other.value;
    }

    function inverse(Fr memory fr) internal view returns (Fr memory) {
        require(fr.value != 0);
        return pow(fr, r_mod - 2);
    }

    function add_assign(Fr memory self, Fr memory other) internal pure {
        self.value = addmod(self.value, other.value, r_mod);
    }

    function sub_assign(Fr memory self, Fr memory other) internal pure {
        self.value = addmod(self.value, r_mod - other.value, r_mod);
    }

    function mul_assign(Fr memory self, Fr memory other) internal pure {
        self.value = mulmod(self.value, other.value, r_mod);
    }

    function pow(Fr memory self, uint256 power) internal view returns (Fr memory) {
        uint256[6] memory input = [32, 32, 32, self.value, power, r_mod];
        uint256[1] memory result;
        bool success;
        assembly {
            success := staticcall(gas(), 0x05, input, 0xc0, result, 0x20)
        }
        require(success);
        return Fr({value: result[0]});
    }

    // Encoding of field elements is: X[0] * z + X[1]
    struct G2Point {
        uint256[2] X;
        uint256[2] Y;
    }

    function P1() internal pure returns (G1Point memory) {
        return G1Point(1, 2);
    }

    function new_g1(uint256 x, uint256 y) internal pure returns (G1Point memory) {
        return G1Point(x, y);
    }

    // function new_g1_checked(uint256 x, uint256 y) internal pure returns (G1Point memory) {
    function new_g1_checked(uint256 x, uint256 y) internal pure returns (G1Point memory) {
        if (x == 0 && y == 0) {
            // point of infinity is (0,0)
            return G1Point(x, y);
        }

        // check encoding
        require(x < q_mod, "x axis isn't valid");
        require(y < q_mod, "y axis isn't valid");
        // check on curve
        uint256 lhs = mulmod(y, y, q_mod); // y^2

        uint256 rhs = mulmod(x, x, q_mod); // x^2
        rhs = mulmod(rhs, x, q_mod); // x^3
        rhs = addmod(rhs, bn254_b_coeff, q_mod); // x^3 + b
        require(lhs == rhs, "is not on curve");

        return G1Point(x, y);
    }

    function new_g2(uint256[2] memory x, uint256[2] memory y) internal pure returns (G2Point memory) {
        return G2Point(x, y);
    }

    function copy_g1(G1Point memory self) internal pure returns (G1Point memory result) {
        result.X = self.X;
        result.Y = self.Y;
    }

    function P2() internal pure returns (G2Point memory) {
        // for some reason ethereum expects to have c1*v + c0 form

        return
            G2Point(
                [
                    0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2,
                    0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed
                ],
                [
                    0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b,
                    0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa
                ]
            );
    }

    function negate(G1Point memory self) internal pure {
        // The prime q in the base field F_q for G1
        if (self.Y == 0) {
            require(self.X == 0);
            return;
        }

        self.Y = q_mod - self.Y;
    }

    function point_add(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {
        point_add_into_dest(p1, p2, r);
        return r;
    }

    function point_add_assign(G1Point memory p1, G1Point memory p2) internal view {
        point_add_into_dest(p1, p2, p1);
    }

    function point_add_into_dest(
        G1Point memory p1,
        G1Point memory p2,
        G1Point memory dest
    ) internal view {
        if (p2.X == 0 && p2.Y == 0) {
            // we add zero, nothing happens
            dest.X = p1.X;
            dest.Y = p1.Y;
            return;
        } else if (p1.X == 0 && p1.Y == 0) {
            // we add into zero, and we add non-zero point
            dest.X = p2.X;
            dest.Y = p2.Y;
            return;
        } else {
            uint256[4] memory input;

            input[0] = p1.X;
            input[1] = p1.Y;
            input[2] = p2.X;
            input[3] = p2.Y;

            bool success;
            assembly {
                success := staticcall(gas(), 6, input, 0x80, dest, 0x40)
            }
            require(success);
        }
    }

    function point_sub_assign(G1Point memory p1, G1Point memory p2) internal view {
        point_sub_into_dest(p1, p2, p1);
    }

    function point_sub_into_dest(
        G1Point memory p1,
        G1Point memory p2,
        G1Point memory dest
    ) internal view {
        if (p2.X == 0 && p2.Y == 0) {
            // we subtracted zero, nothing happens
            dest.X = p1.X;
            dest.Y = p1.Y;
            return;
        } else if (p1.X == 0 && p1.Y == 0) {
            // we subtract from zero, and we subtract non-zero point
            dest.X = p2.X;
            dest.Y = q_mod - p2.Y;
            return;
        } else {
            uint256[4] memory input;

            input[0] = p1.X;
            input[1] = p1.Y;
            input[2] = p2.X;
            input[3] = q_mod - p2.Y;

            bool success = false;
            assembly {
                success := staticcall(gas(), 6, input, 0x80, dest, 0x40)
            }
            require(success);
        }
    }

    function point_mul(G1Point memory p, Fr memory s) internal view returns (G1Point memory r) {
        // https://eips.ethereum.org/EIPS/eip-197
        // Elliptic curve points are encoded as a Jacobian pair (X, Y) where the point at infinity is encoded as (0, 0)
        if (p.X == 0 && p.Y == 1) {
            p.Y = 0;
        }
        point_mul_into_dest(p, s, r);
        return r;
    }

    function point_mul_assign(G1Point memory p, Fr memory s) internal view {
        point_mul_into_dest(p, s, p);
    }

    function point_mul_into_dest(
        G1Point memory p,
        Fr memory s,
        G1Point memory dest
    ) internal view {
        uint256[3] memory input;
        input[0] = p.X;
        input[1] = p.Y;
        input[2] = s.value;
        bool success;
        assembly {
            success := staticcall(gas(), 7, input, 0x60, dest, 0x40)
        }
        require(success);
    }

    function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) {
        require(p1.length == p2.length);
        uint256 elements = p1.length;
        uint256 inputSize = elements * 6;
        uint256[] memory input = new uint256[](inputSize);
        for (uint256 i = 0; i < elements; ) {
            input[i * 6 + 0] = p1[i].X;
            input[i * 6 + 1] = p1[i].Y;
            input[i * 6 + 2] = p2[i].X[0];
            input[i * 6 + 3] = p2[i].X[1];
            input[i * 6 + 4] = p2[i].Y[0];
            input[i * 6 + 5] = p2[i].Y[1];
            unchecked {
                ++i;
            }
        }
        uint256[1] memory out;
        bool success;
        assembly {
            success := staticcall(gas(), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
        }
        require(success);
        return out[0] != 0;
    }

    /// Convenience method for a pairing check for two pairs.
    function pairingProd2(
        G1Point memory a1,
        G2Point memory a2,
        G1Point memory b1,
        G2Point memory b2
    ) internal view returns (bool) {
        G1Point[] memory p1 = new G1Point[](2);
        G2Point[] memory p2 = new G2Point[](2);
        p1[0] = a1;
        p1[1] = b1;
        p2[0] = a2;
        p2[1] = b2;
        return pairing(p1, p2);
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 9999999
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"zero","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"alpha","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"gamma","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[9]","name":"alpha_values","type":"tuple[9]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"eta","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_lookup","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"gamma_lookup","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_plus_one","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_gamma","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"v","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"u","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z_minus_last_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"l_0_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"l_n_minus_one_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"t","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"tp","type":"tuple"}],"internalType":"struct Plonk4VerifierWithAccessToDNext.PartialVerifierState","name":"state","type":"tuple"}],"name":"compute_powers_of_alpha","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"get_verification_key","outputs":[{"components":[{"internalType":"uint256","name":"domain_size","type":"uint256"},{"internalType":"uint256","name":"num_inputs","type":"uint256"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[2]","name":"gate_selectors_commitments","type":"tuple[2]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[8]","name":"gate_setup_commitments","type":"tuple[8]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"permutation_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_selector_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"lookup_tables_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_table_type_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[3]","name":"non_residues","type":"tuple[3]"},{"components":[{"internalType":"uint256[2]","name":"X","type":"uint256[2]"},{"internalType":"uint256[2]","name":"Y","type":"uint256[2]"}],"internalType":"struct PairingsBn254.G2Point[2]","name":"g2_elements","type":"tuple[2]"}],"internalType":"struct VerificationKey","name":"vk","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"domain_size","type":"uint256"},{"internalType":"uint256","name":"num_inputs","type":"uint256"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[2]","name":"gate_selectors_commitments","type":"tuple[2]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[8]","name":"gate_setup_commitments","type":"tuple[8]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"permutation_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_selector_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"lookup_tables_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_table_type_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[3]","name":"non_residues","type":"tuple[3]"},{"components":[{"internalType":"uint256[2]","name":"X","type":"uint256[2]"},{"internalType":"uint256[2]","name":"Y","type":"uint256[2]"}],"internalType":"struct PairingsBn254.G2Point[2]","name":"g2_elements","type":"tuple[2]"}],"internalType":"struct VerificationKey","name":"vk","type":"tuple"},{"components":[{"internalType":"uint256[]","name":"input_values","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"state_polys_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"copy_permutation_grand_product_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"quotient_poly_parts_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[4]","name":"state_polys_openings_at_z","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[1]","name":"state_polys_openings_at_z_omega","type":"tuple[1]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[1]","name":"gate_selectors_openings_at_z","type":"tuple[1]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[3]","name":"copy_permutation_polys_openings_at_z","type":"tuple[3]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"copy_permutation_grand_product_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"quotient_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"linearization_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_s_poly_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_grand_product_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_s_poly_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_grand_product_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_t_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_t_poly_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_selector_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_table_type_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"opening_proof_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"opening_proof_at_z_omega","type":"tuple"}],"internalType":"struct Plonk4VerifierWithAccessToDNext.Proof","name":"proof","type":"tuple"},{"components":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"zero","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"alpha","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"gamma","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[9]","name":"alpha_values","type":"tuple[9]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"eta","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_lookup","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"gamma_lookup","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_plus_one","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_gamma","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"v","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"u","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z_minus_last_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"l_0_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"l_n_minus_one_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"t","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"tp","type":"tuple"}],"internalType":"struct Plonk4VerifierWithAccessToDNext.PartialVerifierState","name":"state","type":"tuple"}],"name":"prepare_queries","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[13]","name":"commitments_at_z","type":"tuple[13]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[13]","name":"values_at_z","type":"tuple[13]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[6]","name":"commitments_at_z_omega","type":"tuple[6]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[6]","name":"values_at_z_omega","type":"tuple[6]"}],"internalType":"struct Plonk4VerifierWithAccessToDNext.Queries","name":"queries","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"domain_size","type":"uint256"},{"internalType":"uint256","name":"num_inputs","type":"uint256"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[2]","name":"gate_selectors_commitments","type":"tuple[2]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[8]","name":"gate_setup_commitments","type":"tuple[8]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"permutation_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_selector_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"lookup_tables_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_table_type_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[3]","name":"non_residues","type":"tuple[3]"},{"components":[{"internalType":"uint256[2]","name":"X","type":"uint256[2]"},{"internalType":"uint256[2]","name":"Y","type":"uint256[2]"}],"internalType":"struct PairingsBn254.G2Point[2]","name":"g2_elements","type":"tuple[2]"}],"internalType":"struct VerificationKey","name":"vk","type":"tuple"},{"components":[{"internalType":"uint256[]","name":"input_values","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"state_polys_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"copy_permutation_grand_product_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point[4]","name":"quotient_poly_parts_commitments","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[4]","name":"state_polys_openings_at_z","type":"tuple[4]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[1]","name":"state_polys_openings_at_z_omega","type":"tuple[1]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[1]","name":"gate_selectors_openings_at_z","type":"tuple[1]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[3]","name":"copy_permutation_polys_openings_at_z","type":"tuple[3]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"copy_permutation_grand_product_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"quotient_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"linearization_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_s_poly_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"lookup_grand_product_commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_s_poly_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_grand_product_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_t_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_t_poly_opening_at_z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_selector_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"lookup_table_type_poly_opening_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"opening_proof_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"opening_proof_at_z_omega","type":"tuple"}],"internalType":"struct Plonk4VerifierWithAccessToDNext.Proof","name":"proof","type":"tuple"},{"components":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"zero","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"alpha","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"gamma","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr[9]","name":"alpha_values","type":"tuple[9]"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"eta","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_lookup","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"gamma_lookup","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_plus_one","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"beta_gamma","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"v","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"u","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"z_minus_last_omega","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"l_0_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"l_n_minus_one_at_z","type":"tuple"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct PairingsBn254.Fr","name":"t","type":"tuple"},{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"tp","type":"tuple"}],"internalType":"struct Plonk4VerifierWithAccessToDNext.PartialVerifierState","name":"state","type":"tuple"}],"name":"rescue_custom_gate_linearization_contribution","outputs":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct PairingsBn254.G1Point","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"public_inputs","type":"uint256[]"},{"internalType":"uint256[]","name":"serialized_proof","type":"uint256[]"}],"name":"verify_serialized_proof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506155d380620000216000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c8063bd5794e211610050578063bd5794e2146100b4578063c2ef6041146100c9578063fec4e96e146100e957600080fd5b8063330deb9f1461006c5780633ec236cb14610094575b600080fd5b61007f61007a36600461471c565b6100fe565b60405190151581526020015b60405180910390f35b6100a76100a236600461507a565b610141565b60405161008b91906151a5565b6100bc610296565b60405161008b91906152f4565b6100dc6100d736600461507a565b610af5565b60405161008b9190615427565b6100fc6100f73660046154c1565b610e59565b005b600080610109610296565b6020810151909150851461011c57600080fd5b600061012a87878787610f07565b90506101368183611360565b979650505050505050565b6040805180820190915260008082526020820152604080516020810190915260008152604080516020810190915260008152608085015161019a9060005b60200201516040805160208101909152600081529051815290565b91506101a68280611645565b60808501516101be9060015b60200201518390611671565b60808401516101d69060015b60200201518390611645565b6101e081836116c7565b60808501516101f090600161017f565b91506101fc8280611645565b608085015161020c9060026101b2565b608084015161021c9060026101ca565b61022681836116c7565b608085015161023690600261017f565b60808601519092506102499060006101ca565b60808501516102599060036101b2565b60808401516102699060036101ca565b61027381836116c7565b606086015161028c90829060015b6020020151906116f3565b9695505050505050565b61029e613fa8565b60016020820152630400000081526102d57f1dba8b5bdd64ef6ce29a9039aca3c0e524395c43b9227b96c75090cc6cc7ec97611732565b60408201526103247f14c289d746e37aa82ec428491881c4732766492a8bc2e8e3cca2000a40c0ea277f2f617a7eb9808ad9843d1e080b7cfbf99d61bb1b02076c905f31adb12731bc4161177f565b6080820151526103747f210b5cc8e6a85d63b65b701b8fb5ad24ff9c41f923432de17fe4ebae04526a8c7f05c10ab17ea731b2b87fb890fa5b10bd3d6832917a616b807a9b640888ebc73161177f565b6080820151602001526103c67f29d4d14adcfe67a2ac690d6369db6b75e82d8ab3124bc4fa1dd145f41ca6949c7e4f6cd229373f1c1f735ccf49aef6a5c32025bc36c3328596dd0db7d87bef6761177f565b6080820151604001526104197f06d15382e8cabae9f98374a9fbdadd424f48e24da7e4c65bf710fd7d7d59a05a7f22e438ad5c51673879ce17073a3d2d29327a97dc3ce61c4f88540e00087695f661177f565b60808201516060015261046c7f274a668dfc485cf192d0086f214146d9e02b3040a5a586df344c53c16a87882b7f15f5bb7ad01f162b70fc77c8ea456d67d15a6ce98acbbfd521222810f8ec0a6661177f565b60808281015101526104be7f0ba53bf4fb0446927857e33978d02abf45948fc68f4091394ae0827a22cf1e477f0720d818751ce5b3f11c716e925f60df4679ea90bed516499bdec066f5ff108f61177f565b608082015160a001526105117f2e986ba2ea495e5ec6af532980b1dc567f1430bfa82f8de07c12fc097c0e04837f1555d189f6164e82d78de1b8313c2e923e616b3c8ed0e350c3b61c94516d0b5861177f565b608082015160c001526105647f0925959592604ca73c917f9b2e029aa2563c318ddcc5ca29c11badb7b880127b7f2b4a430fcb2fa7d6d67d6c358e01cf0524c7df7e1e56442f65b39bc1a105236761177f565b608082015160e001526105b77f28f2a0a95af79ba67e9dd1986bd3190199f661b710a693fc82fb395c126edcbd7f0db75db5de5192d1ba1c24710fc00da16fa8029ac7fe82d855674dcd6d090e0561177f565b6060820151526106077f143471a174dfcb2d9cb5ae621e519387bcc93c9dcfc011160b2f5c5f88e32cbe7f2a0194c0224c3d964223a96c4c99e015719bc879125aa0df3f0715d154e71a3161177f565b60608201516020015261065a7f1423fa82e00ba22c280181afb12c56eea541933eeb5ec39119b0365b6beab4b97f0efdcd3423a38f5e2ecf8c7e4fd46f13189f8fed392ad9d8d393e8ba568b06e461177f565b60a0820151526106aa7f0e9b5b12c1090d62224e64aa1696c009aa59a9c3eec458e781fae773e1f4eca57f1fe3df508c7e9750eb37d9cae5e7437ad11a21fa36530ff821b407b165a79a5561177f565b60a0820151602001526106fd7f25d1a714bd1e258f196e38d6b2826153382c2d04b870d0b7ec250296005129ae7f0883a121b41ca7beaa9de97ecf4417e62aa2eeb9434f24ddacbfed57cbf016a861177f565b60a0820151604001526107507f2f3ede68e854a6b3b14589851cf077a606e2aeb3205c43cc579b7abae39d8f587f178ccd4b1f78fd79ee248e376b6fc8297d5450900d1e15e8c03e3ed2c171ac8c61177f565b60a0820151606001526107a37f1f814e2d87c332e964eeef94ec695eef9d2caaac58b682a43da5107693b06f307f196d56fb01907e66af9303886fd95328d398e5b2b72906882a9d12c1718e2ee261177f565b60c08201526107f27f0ebe0de4a2f39df3b903da484c1641ffdffb77ff87ce4f9508c548659eb22d3c7f12a3209440242d5662729558f1017ed9dcc08fe49a99554dd45f5f15da5e4e0b61177f565b60e0820151526108427f1b7d54f8065ca63bed0bfbb9280a1011b886d07e0c0a26a66ecc96af68c53bf97f2c51121fff5b8f58c302f03c74e0cb176ae5a1d1730dec4696eb9cce3fe284ca61177f565b60e0820151602001526108957f0138733c5faa9db6d4b8df9748081e38405999e511fb22d40f77cf3aef293c447f269bee1c1ac28053238f7fe789f1ea2e481742d6d16ae78ed81e87c254af076561177f565b60e0820151604001526108e87f1b1be7279d59445065a95f01f16686adfa798ec4f1e6845ffcec9b837e88372e7f057c90cb96d8259238ed86b05f629efd55f472a721efeeb56926e979433e6c0e61177f565b60e08201516060015261093b7f2f85df2d6249ccbcc11b91727333cc800459de6ee274f29c657c8d56f6f015637f088e1df178c47116a69c3c8f6d0c5feb530e2a72493694a623b1cceb7d44a76c61177f565b61010082015261094b6005611732565b6101208201515261095c6007611732565b61012082015160200152610970600a611732565b61012082015160026020020181905250610a3260405180604001604052807f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c281526020017f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed81525060405180604001604052807f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b81526020017f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa8152506117aa565b610140820151526040805180820182527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c181527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b060208281019190915282518084019093527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe483527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e5590830152610ae8916117aa565b6101408201516020015290565b610afd61406f565b600260005b6004811015610b805784602001518160048110610b2157610b216154e5565b6020020151835183600d8110610b3957610b396154e5565b602002015260808501518160048110610b5457610b546154e5565b6020020151836020015183600d8110610b6f57610b6f6154e5565b602002015260019182019101610b02565b50606085015151825182600d8110610b9a57610b9a6154e5565b602002015260c084015160006020020151826020015182600d8110610bc157610bc16154e5565b602002015260010160005b610bd860016004615543565b811015610c54578560a001518160048110610bf557610bf56154e5565b6020020151835183600d8110610c0d57610c0d6154e5565b602002015260e08501518160038110610c2857610c286154e5565b6020020151836020015183600d8110610c4357610c436154e5565b602002015260019182019101610bcc565b5060408481015190830151526020840151610c7160016004615543565b60048110610c8157610c816154e5565b6020908102919091015160408401518201526101008501516060840180519190915260a0808701515191519092015260e08601515190840151600090610cd7906040805160208101909152600081529051815290565b905060015b6004811015610d2a57610cff828960e001518360048110610281576102816154e5565b6102408701819052610d129084906117b2565b60a0860151610d22908390611645565b600101610cdc565b508351829084600d8110610d4057610d406154e5565b6020020181905250856101e00151846020015184600d8110610d6457610d646154e5565b602002015260c087015184516001949094019384600d8110610d8857610d886154e5565b6020020181905250856102200151846020015184600d8110610dac57610dac6154e5565b602002015261010087015184516001949094019384600d8110610dd157610dd16154e5565b6020020181905250856102400151846020015184600d8110610df557610df56154e5565b602002015250610160850151604084810180518201929092526101a0870151606080870180519093019190915261018088015183518201526101c0880151825190910152905160809081019290925261020090950151945101939093529392505050565b602081015151600003610e6b57600080fd5b610e756001611732565b608082018051919091526020808301805160408051808501825260008082529251815294518401949094529051835192830190935281529051815260025b6009811015610f02576020830151610ecc908390611645565b6040805160208101909152600081528251815283608001518260098110610ef557610ef56154e5565b6020020152600101610eb3565b505050565b610f0f6140a9565b602c8214610f1c57600080fd5b8367ffffffffffffffff811115610f3557610f35614788565b604051908082528060200260200182016040528015610f5e578160200160208202803683370190505b50815260005b84811015610fae57858582818110610f7e57610f7e6154e5565b9050602002013582600001518281518110610f9b57610f9b6154e5565b6020908102919091010152600101610f64565b506000805b600481101561102857610fff858584818110610fd157610fd16154e5565b905060200201358686610fe48660010190565b818110610ff357610ff36154e5565b905060200201356117c1565b83602001518260048110611015576110156154e5565b6020020152600282019150600101610fb3565b5061105184848381811061103e5761103e6154e5565b905060200201358585610fe48560010190565b604083015260020161106e84848381811061103e5761103e6154e5565b61016083015260020161108c84848381811061103e5761103e6154e5565b61018083015260020160005b60048110156110df576110b6858584818110610fd157610fd16154e5565b836060015182600481106110cc576110cc6154e5565b6020020152600282019150600101611098565b5060005b60048110156111345761110d858584818110611101576111016154e5565b90506020020135611732565b83608001518260048110611123576111236154e5565b6020020152600191820191016110e3565b5060005b600181101561117d57611156858584818110611101576111016154e5565b8360a00151826001811061116c5761116c6154e5565b602002015260019182019101611138565b5060005b60018110156111c65761119f858584818110611101576111016154e5565b8360c0015182600181106111b5576111b56154e5565b602002015260019182019101611181565b5060005b600381101561120f576111e8858584818110611101576111016154e5565b8360e0015182600381106111fe576111fe6154e5565b6020020152600191820191016111ca565b50611225848483818110611101576111016154e5565b610100830152600101611243848483818110611101576111016154e5565b6101a0830152600101611261848483818110611101576111016154e5565b6101c083015260010161127f848483818110611101576111016154e5565b6101e083015260010161129d848483818110611101576111016154e5565b6102008301526001016112bb848483818110611101576111016154e5565b6102208301526001016112d9848483818110611101576111016154e5565b6102408301526001016112f7848483818110611101576111016154e5565b610120830152600101611315848483818110611101576111016154e5565b61014083015260010161133384848381811061103e5761103e6154e5565b61026083015260020161135184848381811061103e5761103e6154e5565b61028083015250949350505050565b60008061136d8484611a37565b905061137a8385836127a8565b151560000361138d57600091505061163f565b60608401516000906113c690825b6020020151604080518082019091526000808252602080830191825283518352929092015190915290565b84516101808401519192506000916113dd91612ab3565b604080516020808201835260008083528451835283518085019094528084529083015291925060015b6004811015611450576114288960600151826004811061139b5761139b6154e5565b91506114348284612b44565b61143e85836117b2565b6114488385611645565b600101611406565b505050506000611461858785610af5565b8051839052610120870151602082015152905061147f858785612b4f565b815160209081019190915261014087015181830180519092015281515190515160006114ab6001611732565b90506114ca604051806040016040528060008152602001600081525090565b60015b600d811015611553576101408801516114e7908490611645565b61150183876000015183600d8110610281576102816154e5565b915061150d85836117b2565b856020015181600d8110611523576115236154e5565b6020020151610220890181905261153a9084611645565b61022088015161154b9085906116c7565b6001016114cd565b50610140870151611565908390611645565b6000611582838760400151600060068110610281576102816154e5565b6060870151519091506115958185611645565b60015b600681101561161e576101408a01516115b2908690611645565b6115cc8589604001518360068110610281576102816154e5565b93506115d883856117b2565b876060015181600681106115ee576115ee6154e5565b60200201516102208b018190526116059086611645565b6102208a01516116169083906116c7565b600101611598565b506116338b61014001518d8b89868a87612fa1565b99505050505050505050505b92915050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001815183510990915250565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181516116be907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001615543565b83510890915250565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001815183510890915250565b6040805180820190915260008082526020820152825115801561171a575082602001516001145b1561172757600060208401525b61163f83838361313c565b6040805160208101909152600081527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001821061176d57600080fd5b50604080516020810190915290815290565b60408051808201909152600080825260208201525b5060408051808201909152918252602082015290565b6117946142b7565b6117bd82828461317e565b5050565b6040805180820190915260008082526020820152821580156117e1575081155b1561180257604051806040016040528084815260200183815250905061163f565b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478310611890576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7820617869732069736e27742076616c6964000000000000000000000000000060448201526064015b60405180910390fd5b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478210611919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7920617869732069736e27742076616c696400000000000000000000000000006044820152606401611887565b60007f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47838409905060007f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4785860990507f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4785820990507f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47600382089050808214611a1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6973206e6f74206f6e20637572766500000000000000000000000000000000006044820152606401611887565b50506040805180820190915292835250602082015290565b611a3f6142d7565b60408051606081018252600080825260208201819052918101829052905b8360200151811015611aa157611a9985600001518281518110611a8257611a826154e5565b60200260200101518361320e90919063ffffffff16565b600101611a5d565b5060005b6004811015611beb57611be385602001518260048110611ac757611ac76154e5565b602002015183908051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a01949094528383018190528387019b909b52828a0181905284518084038b0181529284018552825192880192909220909a528451835180880198909852998701989098529185019790975283850195909552855180840390940184529190930190935280519101209052565b600101611aa5565b50611bf5816132f1565b60a08301526101608401518051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a01949094528383018190528387019b909b52828a0181905284518084038b01815292840185528251928801929092208b528551845180890199909952908801999099529286019790975284860191909152805180850390950185529290940190915281519101209052611d1b816132f1565b6040830152611d29816132f1565b6060830152604084810151805183516020808601805186516000818501819052602480830187905260448084019490945260648084018990528a518085038201815260849485018c528051908801208c5285518b517c0100000000000000000000000000000000000000000000000000000000818a018190528185019a909a5280870191909152808201999099528a51808a03820181529884018b52885198870198909820808652988601518b518b51808901949094528383018190528386019a909a528289018190528a518084038a0181529284018b528251928701929092208b5284518a5180880198909852908701989098529185019690965283850152855180840390940184529190930190935280519101209052611e4a816132f1565b60c0830152611e58816132f1565b60e08301526101808401518051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a01949094528383018190528387019b909b52828a0181905284518084038b01815292840185528251928801929092208b528551845180890199909952908801999099529286019790975284860191909152805180850390950185529290940190915281519101209052611f7e816132f1565b602083015260005b6004811015611fb057611fa885606001518260048110611ac757611ac76154e5565b600101611f86565b50611fba816132f1565b610180830152610120840151518151602080840180516040805160008186015260248082018790526044808301949094526064808301899052835180840382018152608493840185528051908801208a52855184517c0100000000000000000000000000000000000000000000000000000000818a015292830198909852938101969096528583019690965280518086039092018252939094019092528251920191909120905260005b60048110156121325761212a85608001518260048110612086576120866154e5565b6020908102919091015151845185830180516040805160008188015260248082018690526044808301949094526064808301889052835180840382018152608493840185528051908a01208c52855184517c0100000000000000000000000000000000000000000000000000000000818c01529283019790975293810195909552848301959095528051808503909201825292909301909152815191909201209052565b600101612064565b5060005b6001811015612160576121588560a001518260018110612086576120866154e5565b600101612136565b5060005b600181101561218e576121868560c001518260018110612086576120866154e5565b600101612164565b5060005b60038110156121bc576121b48560e001518260038110612086576120866154e5565b600101612192565b506101808201516040805160208101825260008152915182526101a084018290528401516121ea9190611645565b61010084015151815160208084018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208b52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b038201815299840185528951998801999099208087526101e08e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526102208e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526102408e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526101a08e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526101c08e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526102008e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526101408e0151518b518651808b019590955284840181905284880192909252838b0181905285518085038c01815293850186528351938901939093208b5286518551808a019a909a5291890152938701939093528587019290925280518086039096018652930190925282519201919091209052612599816132f1565b6101408301526102608401518051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a018590528084018290528088019c909c528b8b018290528551808d038c0181529b850186528b519b89019b909b208c5286518551808a018b90528084019c909c528b8701528a8a01528351808b038a01815299830184528951998701999099208086526102808e015180518c518651808b01869052808e0182905280890194909452838c0182905286518085038d01815293860187528351938a01939093208d5287518651808b018c9052808e019490945283880152828b015284518083038b0181529184018552815191880191909120808752908701518b518551808a0194909452838c0181905283870192909252828a0181905284518084038b01815292840185528251928801929092208b52855184518089019990995299880152928601979097528486019190915280518085039095018552929094019091528151910120905261279b816132f1565b6101608301525092915050565b600080846020015167ffffffffffffffff8111156127c8576127c8614788565b6040519080825280602002602001820160405280156127f1578160200160208202803683370190505b50905060005b81518110156128265780828281518110612813576128136154e5565b60209081029190910101526001016127f7565b50600085602001511161283857600080fd5b60006128446000611732565b905060005b86602001518110156128c25761286e81886000015189604001518861018001516133e1565b610220860152855180516128a99161289d9184908110612890576128906154e5565b6020026020010151611732565b61022087015190611645565b6102208501516128ba9083906116c7565b600101612849565b5060c08501516128db9060005b60200201518290611645565b610140850151604080516020810190915260008152905181526128fe81836116c7565b61290785610e59565b608085015160009061291a90600461017f565b90506129348761010001518261164590919063ffffffff16565b61294060016004615543565b60031461294c57600080fd5b60408051602081019091526000815260005b60038110156129e0576129808960e00151826003811061017f5761017f6154e5565b915061299988604001518361164590919063ffffffff16565b6129be896080015182600481106129b2576129b26154e5565b602002015183906116c7565b60608801516129ce9083906116c7565b6129d88383611645565b60010161295e565b5060808801516129f190600361017f565b9050612a0a8760600151826116c790919063ffffffff16565b612a148282611645565b612a1e8383611671565b6000612a338a6000015189610180015161348f565b6080890151909150612a469060056128cf565b612a508482611671565b6000612a5d8b8b8b613515565b9050612a6985826116c7565b6101208a0151604080516020810190915260008152905181528b516101808b0151612a9e91612a9791613765565b8290611645565b945194519094149a9950505050505050505050565b604080516020808201835260008252825160c0810184528181528082018290529283015283516060830152608082018390527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a083015290612b1461448b565b600060208260c08560055afa905080612b2c57600080fd5b50604080516020810190915290518152949350505050565b6117bd82828461313c565b6040805180820190915260008082526020820152612b6e60008061177f565b90506000612b9d8460800151600060048110612b8c57612b8c6154e5565b602002015160808701516000610281565b9050612ba982826117b2565b6080840151612bc5906001602002015160808701516001610281565b9050612bd182826117b2565b6080840151612bed906002602002015160808701516002610281565b9050612bf982826117b2565b6080840151612c15906003602002015160808701516003610281565b9050612c2182826117b2565b6080840151600090612c33908261017f565b6080860151909150612c469060016128cf565b6080860151612c589082906004610281565b9150612c6483836117b2565b6080850151612c7490600061017f565b6080860151909150612c879060026128cf565b6080860151612c999082906005610281565b9150612ca583836117b2565b608086015160c00151612cb99084906117b2565b60a0850151516080870151612cd091906007610281565b9150612cdc83836117b2565b60c085015151612ced908490612b44565b6000612cfa878787610141565b9050612d0684826117b2565b612d1260016004615543565b600314612d1e57600080fd5b6000612d2a6001611732565b90506000612d48876080015160046009811061017f5761017f6154e5565b905060005b6004811015612e105761018088015160408051602081019091526000815290518152945080600003612d8857612d838584611645565b612db9565b6101208a0151612db990612d9d600184615543565b60038110612dad57612dad6154e5565b60200201518690611645565b6040880151612dc9908690611645565b6060880151612dd99086906116c7565b612dfe89608001518260048110612df257612df26154e5565b602002015186906116c7565b612e088286611645565b600101612d4d565b506040880151612e2090826116f3565b9450612e2c86866117b2565b6080870151612e3c90600461017f565b9050612e5587604001518261164590919063ffffffff16565b610100880151612e66908290611645565b60005b612e7560016004615543565b811015612ee957612e958960e00151826003811061017f5761017f6154e5565b9450612eae88604001518661164590919063ffffffff16565b6060880151612ebe9086906116c7565b612ed789608001518260048110612df257612df26154e5565b612ee18286611645565b600101612e69565b5060a0890151612efc9082906003610281565b9450612f088686613794565b612f2260008a600001518b604001518a61018001516133e1565b6101e0880181905251600003612f3757600080fd5b506101e0860151604080516020810190915260008152905181526080870151612f619060056128cf565b6040880151612f7090826116f3565b9450612f7c86866117b2565b6000612f88898961379f565b9050612f9487826117b2565b5050505050509392505050565b60408051808201909152600080825260208083018281528751845290870151905290612fdb87610160015186612b4490919063ffffffff16565b612fe581866117b2565b60408051602081019091526000815283518152610160880151613009908290611645565b61301381866116c7565b600061304b82613045604080518082018252600080825260209182015281518083019092526001825260029082015290565b906116f3565b90506130578382613794565b6101808901516102608b015161306c916116f3565b9050600061308f8a6101a001516040805160208101909152600081529051815290565b90506130a98a61016001518261164590919063ffffffff16565b6102808b01516000906130bc90836116f3565b90506130c883826117b2565b6130d285846117b2565b60006130f18c61016001518e61028001516116f390919063ffffffff16565b905061310b8d6102600151826117b290919063ffffffff16565b61311481613a6d565b8d5160208f015161312788838584613abf565b98505050505050505050979650505050505050565b6131446144a9565b835181526020840151816001602002015282518160026020020152600060408360608460075afa90508061317757600080fd5b5050505050565b815115801561318f57506020820151155b156131a7578251815260209283015192019190915250565b82511580156131b857506020830151155b156131cd578151815260209182015191015250565b6131d56144c7565b8351815260208085015181830152835160408301528301518160035b6020020152600060408360808460065afa90508061317757600080fd5b815160208084015160405160009281019290925260248201839052604482015260648101839052608401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152918152815160209283012085528482015190517c01000000000000000000000000000000000000000000000000000000009281019290925260248201839052604482015260648101839052608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020918201209301929092525050565b604080516020810190915260008152815160208084015160408086015190517c0200000000000000000000000000000000000000000000000000000000938101939093526024830193909352604482015260e09190911b7fffffffff000000000000000000000000000000000000000000000000000000001660648201526000906068016040516020818303038152906040528051906020012090506001836040018181516133a09190615556565b63ffffffff1690525060408051602081019091527f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91909116815292915050565b6040805160208101909152600081528385106133fc57600080fd5b60006134086001611732565b905060006134168588612ab3565b90506134228487612ab3565b925061342e8383611671565b825160000361343c57600080fd5b6134468382611645565b604080516020810190915260008152845181526134638183611671565b61346f612a9788611732565b61347881613bbf565b90506134848482611645565b505050949350505050565b60408051602081019091526000815260006134aa6001611732565b905060006134b785611732565b604080516020810190915260008152855181529091506134d78184611671565b6134e18183611645565b6134ea81613bbf565b90506134f68587612ab3565b93506135028484611671565b61350c8482611645565b50505092915050565b604080516020810190915260008152604080516020810190915260008152600061353f6001611732565b905061355f8460c001516040805160208101909152600081529051815290565b610100850181905261357190826116c7565b61010084015160408051602081019091526000815290518152610120850181905260e08501516135a19190611645565b6101a08501516040805160208101909152600081529051815291506135d38460c001518361164590919063ffffffff16565b6101208401516135e49083906116c7565b6101c08501516135f5908390611645565b60808401516136059060066101ca565b60006136266001886000015161361b9190615543565b604089015190612ab3565b90506136478561018001516040805160208101909152600081529051815290565b6101c086018190526136599082611671565b6101c085015161366a908490611645565b61367484846116c7565b61368e6000886000015189604001518861018001516133e1565b6101e0860181905260408051602081019091526000815290518152608086015160e001519093506136c0908490611645565b6136ca8484611671565b60006136ec600189600001516136e09190615543565b61012088015190612ab3565b9050613714600189600001516137029190615543565b895160408b01516101808a01516133e1565b610200870181905260408051602081019091526000815290518152935061373b8482611645565b60808601516101000151613750908590611645565b61375a8585611671565b505050509392505050565b60408051602081019091526000815261377e8284612ab3565b905061163f61378d6001611732565b8290611671565b6117bd828284613c10565b604080518082019091526000808252602082015260006137bf6000611732565b90506137d76040518060200160405280600081525090565b60408051602080820183526000918290526101c0880151835191820190935290815290518152608085015161380d9060066128cf565b6101c085015161381e908290611645565b61016086015160009061383190836116f3565b905061383d85826117b2565b61020087015160408051602081019091526000815290518152915061386f8660c001518361164590919063ffffffff16565b6101e08701516138809083906116c7565b6101208601516138919083906116c7565b60408051602081019091526000815260006138ac6001611732565b90506138c46040518060200160405280600081525090565b60005b6138d360016004615543565b811015613921576138f38b60800151826004811061017f5761017f6154e5565b91506138ff8284611645565b61390984836116c7565b60a08a0151613919908490611645565b6001016138c7565b506102408a01516040805160208101909152600081529051815295506139478683611645565b61395183876116c7565b6102208a0151613962908490611645565b60e08901516139729084906116c7565b61397c8584611645565b61010089015161398d908690611645565b6040805160208101909152600081528751815295506139ac8686611671565b60808901518695506139bf906006612dad565b6101c08901516139d0908690611645565b6101e08901516040805160208101909152600081529051815260808a0151909650613a049060075b60200201518790611645565b613a0e85876116c7565b6102008901516040805160208101909152600081529051815260808a0151909650613a3a9060086139f8565b613a4485876116c7565b6101808a0151613a5490866116f3565b9350613a6088856117b2565b5050505050505092915050565b8060200151600003613a8857805115613a8557600080fd5b50565b6020810151613ab7907f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47615543565b602090910152565b60408051600280825260608201909252600091829190816020015b6040805180820190915260008082526020820152815260200190600190039081613ada5750506040805160028082526060820190925291925060009190602082015b613b246142b7565b815260200190600190039081613b1c5790505090508682600081518110613b4d57613b4d6154e5565b60200260200101819052508482600181518110613b6c57613b6c6154e5565b60200260200101819052508581600081518110613b8b57613b8b6154e5565b60200260200101819052508381600181518110613baa57613baa6154e5565b60200260200101819052506101368282613cde565b6040805160208101909152600081528151600003613bdc57600080fd5b61163f82613c0b60027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001615543565b612ab3565b8151158015613c2157506020820151155b15613c39578251815260209283015192019190915250565b8251158015613c4a57506020830151155b15613c8c57815181526020820151613c82907f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47615543565b6020909101525050565b613c946144c7565b835181526020808501518183015283516040830152830151613cd6907f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47615543565b8160036131f1565b60008151835114613cee57600080fd5b82516000613cfd826006615573565b905060008167ffffffffffffffff811115613d1a57613d1a614788565b604051908082528060200260200182016040528015613d43578160200160208202803683370190505b50905060005b83811015613f7457868181518110613d6357613d636154e5565b60200260200101516000015182826006613d7d9190615573565b613d8890600061558a565b81518110613d9857613d986154e5565b602002602001018181525050868181518110613db657613db66154e5565b60200260200101516020015182826006613dd09190615573565b613ddb90600161558a565b81518110613deb57613deb6154e5565b602002602001018181525050858181518110613e0957613e096154e5565b6020908102919091010151515182613e22836006615573565b613e2d90600261558a565b81518110613e3d57613e3d6154e5565b602002602001018181525050858181518110613e5b57613e5b6154e5565b60209081029190910181015151015182613e76836006615573565b613e8190600361558a565b81518110613e9157613e916154e5565b602002602001018181525050858181518110613eaf57613eaf6154e5565b602002602001015160200151600060028110613ecd57613ecd6154e5565b602002015182613ede836006615573565b613ee990600461558a565b81518110613ef957613ef96154e5565b602002602001018181525050858181518110613f1757613f176154e5565b602002602001015160200151600160028110613f3557613f356154e5565b602002015182613f46836006615573565b613f5190600561558a565b81518110613f6157613f616154e5565b6020908102919091010152600101613d49565b50613f7d61448b565b6000602082602086026020860160085afa905080613f9a57600080fd5b505115159695505050505050565b6040518061016001604052806000815260200160008152602001613fd86040518060200160405280600081525090565b8152602001613fe56144e5565b8152602001613ff261451e565b8152602001613fff61454a565b8152602001614021604051806040016040528060008152602001600081525090565b815260200161402e61454a565b8152602001614050604051806040016040528060008152602001600081525090565b815260200161405d614573565b815260200161406a6145a7565b905290565b60405180608001604052806140826145d4565b815260200161408f614600565b815260200161409c614623565b815260200161406a61464d565b604051806102a00160405280606081526020016140c461454a565b81526020016140e6604051806040016040528060008152602001600081525090565b81526020016140f361454a565b815260200161410061466e565b8152604080518082018252600060208083018281528352808501929092528251808401845291820190815281529082015260600161413c614573565b81526020016141576040518060200160405280600081525090565b81526020016141726040518060200160405280600081525090565b815260200161418d6040518060200160405280600081525090565b81526020016141af604051806040016040528060008152602001600081525090565b81526020016141d1604051806040016040528060008152602001600081525090565b81526020016141ec6040518060200160405280600081525090565b81526020016142076040518060200160405280600081525090565b81526020016142226040518060200160405280600081525090565b815260200161423d6040518060200160405280600081525090565b81526020016142586040518060200160405280600081525090565b81526020016142736040518060200160405280600081525090565b8152602001614295604051806040016040528060008152602001600081525090565b815260200161406a604051806040016040528060008152602001600081525090565b60405180604001604052806142ca61468f565b815260200161406a61468f565b604080516102808101825260006102608201818152825282516020808201855282825280840191909152835180820185528281528385015283519081019093528252906060820190815260200161432c6146ad565b81526020016143476040518060200160405280600081525090565b81526020016143626040518060200160405280600081525090565b815260200161437d6040518060200160405280600081525090565b81526020016143986040518060200160405280600081525090565b81526020016143b36040518060200160405280600081525090565b81526020016143ce6040518060200160405280600081525090565b81526020016143e96040518060200160405280600081525090565b81526020016144046040518060200160405280600081525090565b815260200161441f6040518060200160405280600081525090565b815260200161443a6040518060200160405280600081525090565b81526020016144556040518060200160405280600081525090565b81526020016144706040518060200160405280600081525090565b81526020016142956040518060200160405280600081525090565b60405180602001604052806001906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b60405180604001604052806002905b60408051808201909152600080825260208201528152602001906001900390816144f45790505090565b6040805161014081019091526000610100820181815261012083019190915281526007602082016144f4565b6040805160c0810190915260006080820181815260a083019190915281526003602082016144f4565b60405180606001604052806003905b6040805160208101909152600081528152602001906001900390816145825790505090565b60405180604001604052806002905b6145be6142b7565b8152602001906001900390816145b65790505090565b604080516101e0810190915260006101a082018181526101c08301919091528152600c602082016144f4565b604080516101c0810190915260006101a082019081528152600c60208201614582565b604080516101008101909152600060c0820181815260e083019190915281526005602082016144f4565b6040805160e08101909152600060c082019081528152600560208201614582565b6040805160a081019091526000608082019081528152600360208201614582565b60405180604001604052806002906020820280368337509192915050565b604080516101408101909152600061012082019081528152600860208201614582565b60008083601f8401126146e257600080fd5b50813567ffffffffffffffff8111156146fa57600080fd5b6020830191508360208260051b850101111561471557600080fd5b9250929050565b6000806000806040858703121561473257600080fd5b843567ffffffffffffffff8082111561474a57600080fd5b614756888389016146d0565b9096509450602087013591508082111561476f57600080fd5b5061477c878288016146d0565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156147da576147da614788565b60405290565b6040516102a0810167ffffffffffffffff811182821017156147da576147da614788565b604051610260810167ffffffffffffffff811182821017156147da576147da614788565b604051610160810167ffffffffffffffff811182821017156147da576147da614788565b6040516080810167ffffffffffffffff811182821017156147da576147da614788565b60006020828403121561488157600080fd5b6040516020810181811067ffffffffffffffff821117156148a4576148a4614788565b6040529135825250919050565b6000604082840312156148c357600080fd5b6148cb6147b7565b9050813581526020820135602082015292915050565b600082601f8301126148f257600080fd5b6148fa6147b7565b80608084018581111561490c57600080fd5b845b818110156149305761492087826148b1565b845260209093019260400161490e565b509095945050505050565b600082601f83011261494c57600080fd5b60408051610100810181811067ffffffffffffffff8211171561497157614971614788565b82528061020085018681111561498657600080fd5b855b818110156149a95761499a88826148b1565b83526020909201918401614988565b50919695505050505050565b600082601f8301126149c657600080fd5b6149ce61484c565b806101008401858111156149e157600080fd5b845b81811015614930576149f587826148b1565b84526020909301926040016149e3565b600082601f830112614a1657600080fd5b6040516060810181811067ffffffffffffffff82111715614a3957614a39614788565b604052806060840185811115614a4e57600080fd5b845b81811015614a7057614a62878261486f565b835260209283019201614a50565b509195945050505050565b600082601f830112614a8c57600080fd5b614a946147b7565b806040840185811115614aa657600080fd5b845b81811015614930578035845260209384019301614aa8565b600082601f830112614ad157600080fd5b614ad96147b7565b80610100840185811115614aec57600080fd5b845b818110156149305760808188031215614b075760008081fd5b614b0f6147b7565b614b198883614a7b565b8152614b288860408401614a7b565b6020828101919091529085529390930192608001614aee565b600082601f830112614b5257600080fd5b8135602067ffffffffffffffff80831115614b6f57614b6f614788565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108482111715614bb257614bb2614788565b604052938452858101830193838101925087851115614bd057600080fd5b83870191505b8482101561013657813583529183019190830190614bd6565b600082601f830112614c0057600080fd5b614c0861484c565b806080840185811115614c1a57600080fd5b845b8181101561493057614c2e878261486f565b845260209384019301614c1c565b600082601f830112614c4d57600080fd5b604051602080820182811067ffffffffffffffff82111715614c7157614c71614788565b6040528184820186811115614c8557600080fd5b855b81811015614ca657614c99888261486f565b8352918301918301614c87565b50929695505050505050565b60006105a08284031215614cc557600080fd5b614ccd6147e0565b9050813567ffffffffffffffff811115614ce657600080fd5b614cf284828501614b41565b825250614d0283602084016149b5565b6020820152610120614d16848285016148b1565b6040830152610160614d2a858286016149b5565b6060840152610260614d3e86828701614bef565b6080850152614d51866102e08701614c3c565b60a0850152614d64866103008701614c3c565b60c0850152614d77866103208701614a05565b60e0850152614d8a86610380870161486f565b610100850152614d9e866103a0870161486f565b83850152614db0866103c0870161486f565b610140850152614dc4866103e087016148b1565b82850152614dd68661042087016148b1565b610180850152614dea86610460870161486f565b6101a0850152614dfe86610480870161486f565b6101c0850152614e12866104a0870161486f565b6101e0850152614e26866104c0870161486f565b610200850152614e3a866104e0870161486f565b610220850152614e4e86610500870161486f565b610240850152614e628661052087016148b1565b81850152505050614e778361056084016148b1565b61028082015292915050565b600082601f830112614e9457600080fd5b60405161012080820182811067ffffffffffffffff82111715614eb957614eb9614788565b60405283018185821115614ecc57600080fd5b845b82811015614a7057614ee0878261486f565b825260209182019101614ece565b60006103808284031215614f0157600080fd5b614f09614804565b9050614f15838361486f565b8152614f24836020840161486f565b6020820152614f36836040840161486f565b6040820152614f48836060840161486f565b6060820152614f5a8360808401614e83565b60808201526101a0614f6e8482850161486f565b60a08301526101c0614f828582860161486f565b60c08401526101e0614f968682870161486f565b60e0850152610200614faa8782880161486f565b610100860152610220614fbf8882890161486f565b610120870152610240614fd489828a0161486f565b610140880152614fe8896102608a0161486f565b610160880152614ffc896102808a0161486f565b610180880152615010896102a08a0161486f565b86880152615022896102c08a0161486f565b85880152615034896102e08a0161486f565b84880152615046896103008a0161486f565b83880152615058896103208a0161486f565b8288015261506a896103408a016148b1565b8188015250505050505092915050565b6000806000838503610a6081121561509157600080fd5b6106c0808212156150a157600080fd5b6150a9614828565b915085358252602086013560208301526150c6876040880161486f565b60408301526150d887606088016148e1565b60608301526150ea8760e0880161493b565b60808301526150fd876102e088016149b5565b60a0830152615110876103e088016148b1565b60c08301526151238761042088016149b5565b60e08301526151368761052088016148b1565b61010083015261514a876105608801614a05565b61012083015261515e876105c08801614ac0565b61014083015290935084013567ffffffffffffffff81111561517f57600080fd5b61518b86828701614cb2565b92505061519c856106e08601614eee565b90509250925092565b81518152602080830151908201526040810161163f565b8060005b60028110156151f4576151de84835180518252602090810151910152565b60409390930192602091909101906001016151c0565b50505050565b8060005b60088110156151f45761521c84835180518252602090810151910152565b60409390930192602091909101906001016151fe565b8060005b60048110156151f45761525484835180518252602090810151910152565b6040939093019260209190910190600101615236565b8060005b60038110156151f45781515184526020938401939091019060010161526e565b8060005b60028110156151f4578151845260209384019390910190600101615292565b8060005b60028110156151f45781516152cb85825161528e565b602090810151906152df604087018361528e565b608095909501949290920191506001016152b5565b60006106c0820190508251825260208301516020830152604083015161531d6040840182519052565b50606083015161533060608401826151bc565b50608083015161534360e08401826151fa565b5060a08301516153576102e0840182615232565b5060c083015180516103e08401526020015161040083015260e0830151615382610420840182615232565b506101008301518051610520840152602001516105408301526101208301516153af61056084018261526a565b506101408301516153c46105c08401826152b1565b5092915050565b8060005b60068110156151f4576153ed84835180518252602090810151910152565b60409390930192602091909101906001016153cf565b8060005b60068110156151f457815151845260209384019390910190600101615407565b81516107208201908260005b600d8110156154675761545182845180518252602090810151910152565b6020929092019160409190910190600101615433565b505050602080840151610340840160005b600d8110156154965782515182529183019190830190600101615478565b5050505060408301516154ad6104e08401826153cb565b5060608301516153c4610660840182615403565b600061038082840312156154d457600080fd5b6154de8383614eee565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561163f5761163f615514565b63ffffffff8181168382160190808211156153c4576153c4615514565b808202811582820484141761163f5761163f615514565b8082018082111561163f5761163f61551456fea2646970667358221220d2f17e9a0c25b77d7be3c1b56c33d3a035f0c73e0cf8dea1efb788c1f63f7bb364736f6c63430008110033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100675760003560e01c8063bd5794e211610050578063bd5794e2146100b4578063c2ef6041146100c9578063fec4e96e146100e957600080fd5b8063330deb9f1461006c5780633ec236cb14610094575b600080fd5b61007f61007a36600461471c565b6100fe565b60405190151581526020015b60405180910390f35b6100a76100a236600461507a565b610141565b60405161008b91906151a5565b6100bc610296565b60405161008b91906152f4565b6100dc6100d736600461507a565b610af5565b60405161008b9190615427565b6100fc6100f73660046154c1565b610e59565b005b600080610109610296565b6020810151909150851461011c57600080fd5b600061012a87878787610f07565b90506101368183611360565b979650505050505050565b6040805180820190915260008082526020820152604080516020810190915260008152604080516020810190915260008152608085015161019a9060005b60200201516040805160208101909152600081529051815290565b91506101a68280611645565b60808501516101be9060015b60200201518390611671565b60808401516101d69060015b60200201518390611645565b6101e081836116c7565b60808501516101f090600161017f565b91506101fc8280611645565b608085015161020c9060026101b2565b608084015161021c9060026101ca565b61022681836116c7565b608085015161023690600261017f565b60808601519092506102499060006101ca565b60808501516102599060036101b2565b60808401516102699060036101ca565b61027381836116c7565b606086015161028c90829060015b6020020151906116f3565b9695505050505050565b61029e613fa8565b60016020820152630400000081526102d57f1dba8b5bdd64ef6ce29a9039aca3c0e524395c43b9227b96c75090cc6cc7ec97611732565b60408201526103247f14c289d746e37aa82ec428491881c4732766492a8bc2e8e3cca2000a40c0ea277f2f617a7eb9808ad9843d1e080b7cfbf99d61bb1b02076c905f31adb12731bc4161177f565b6080820151526103747f210b5cc8e6a85d63b65b701b8fb5ad24ff9c41f923432de17fe4ebae04526a8c7f05c10ab17ea731b2b87fb890fa5b10bd3d6832917a616b807a9b640888ebc73161177f565b6080820151602001526103c67f29d4d14adcfe67a2ac690d6369db6b75e82d8ab3124bc4fa1dd145f41ca6949c7e4f6cd229373f1c1f735ccf49aef6a5c32025bc36c3328596dd0db7d87bef6761177f565b6080820151604001526104197f06d15382e8cabae9f98374a9fbdadd424f48e24da7e4c65bf710fd7d7d59a05a7f22e438ad5c51673879ce17073a3d2d29327a97dc3ce61c4f88540e00087695f661177f565b60808201516060015261046c7f274a668dfc485cf192d0086f214146d9e02b3040a5a586df344c53c16a87882b7f15f5bb7ad01f162b70fc77c8ea456d67d15a6ce98acbbfd521222810f8ec0a6661177f565b60808281015101526104be7f0ba53bf4fb0446927857e33978d02abf45948fc68f4091394ae0827a22cf1e477f0720d818751ce5b3f11c716e925f60df4679ea90bed516499bdec066f5ff108f61177f565b608082015160a001526105117f2e986ba2ea495e5ec6af532980b1dc567f1430bfa82f8de07c12fc097c0e04837f1555d189f6164e82d78de1b8313c2e923e616b3c8ed0e350c3b61c94516d0b5861177f565b608082015160c001526105647f0925959592604ca73c917f9b2e029aa2563c318ddcc5ca29c11badb7b880127b7f2b4a430fcb2fa7d6d67d6c358e01cf0524c7df7e1e56442f65b39bc1a105236761177f565b608082015160e001526105b77f28f2a0a95af79ba67e9dd1986bd3190199f661b710a693fc82fb395c126edcbd7f0db75db5de5192d1ba1c24710fc00da16fa8029ac7fe82d855674dcd6d090e0561177f565b6060820151526106077f143471a174dfcb2d9cb5ae621e519387bcc93c9dcfc011160b2f5c5f88e32cbe7f2a0194c0224c3d964223a96c4c99e015719bc879125aa0df3f0715d154e71a3161177f565b60608201516020015261065a7f1423fa82e00ba22c280181afb12c56eea541933eeb5ec39119b0365b6beab4b97f0efdcd3423a38f5e2ecf8c7e4fd46f13189f8fed392ad9d8d393e8ba568b06e461177f565b60a0820151526106aa7f0e9b5b12c1090d62224e64aa1696c009aa59a9c3eec458e781fae773e1f4eca57f1fe3df508c7e9750eb37d9cae5e7437ad11a21fa36530ff821b407b165a79a5561177f565b60a0820151602001526106fd7f25d1a714bd1e258f196e38d6b2826153382c2d04b870d0b7ec250296005129ae7f0883a121b41ca7beaa9de97ecf4417e62aa2eeb9434f24ddacbfed57cbf016a861177f565b60a0820151604001526107507f2f3ede68e854a6b3b14589851cf077a606e2aeb3205c43cc579b7abae39d8f587f178ccd4b1f78fd79ee248e376b6fc8297d5450900d1e15e8c03e3ed2c171ac8c61177f565b60a0820151606001526107a37f1f814e2d87c332e964eeef94ec695eef9d2caaac58b682a43da5107693b06f307f196d56fb01907e66af9303886fd95328d398e5b2b72906882a9d12c1718e2ee261177f565b60c08201526107f27f0ebe0de4a2f39df3b903da484c1641ffdffb77ff87ce4f9508c548659eb22d3c7f12a3209440242d5662729558f1017ed9dcc08fe49a99554dd45f5f15da5e4e0b61177f565b60e0820151526108427f1b7d54f8065ca63bed0bfbb9280a1011b886d07e0c0a26a66ecc96af68c53bf97f2c51121fff5b8f58c302f03c74e0cb176ae5a1d1730dec4696eb9cce3fe284ca61177f565b60e0820151602001526108957f0138733c5faa9db6d4b8df9748081e38405999e511fb22d40f77cf3aef293c447f269bee1c1ac28053238f7fe789f1ea2e481742d6d16ae78ed81e87c254af076561177f565b60e0820151604001526108e87f1b1be7279d59445065a95f01f16686adfa798ec4f1e6845ffcec9b837e88372e7f057c90cb96d8259238ed86b05f629efd55f472a721efeeb56926e979433e6c0e61177f565b60e08201516060015261093b7f2f85df2d6249ccbcc11b91727333cc800459de6ee274f29c657c8d56f6f015637f088e1df178c47116a69c3c8f6d0c5feb530e2a72493694a623b1cceb7d44a76c61177f565b61010082015261094b6005611732565b6101208201515261095c6007611732565b61012082015160200152610970600a611732565b61012082015160026020020181905250610a3260405180604001604052807f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c281526020017f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed81525060405180604001604052807f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b81526020017f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa8152506117aa565b610140820151526040805180820182527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c181527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b060208281019190915282518084019093527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe483527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e5590830152610ae8916117aa565b6101408201516020015290565b610afd61406f565b600260005b6004811015610b805784602001518160048110610b2157610b216154e5565b6020020151835183600d8110610b3957610b396154e5565b602002015260808501518160048110610b5457610b546154e5565b6020020151836020015183600d8110610b6f57610b6f6154e5565b602002015260019182019101610b02565b50606085015151825182600d8110610b9a57610b9a6154e5565b602002015260c084015160006020020151826020015182600d8110610bc157610bc16154e5565b602002015260010160005b610bd860016004615543565b811015610c54578560a001518160048110610bf557610bf56154e5565b6020020151835183600d8110610c0d57610c0d6154e5565b602002015260e08501518160038110610c2857610c286154e5565b6020020151836020015183600d8110610c4357610c436154e5565b602002015260019182019101610bcc565b5060408481015190830151526020840151610c7160016004615543565b60048110610c8157610c816154e5565b6020908102919091015160408401518201526101008501516060840180519190915260a0808701515191519092015260e08601515190840151600090610cd7906040805160208101909152600081529051815290565b905060015b6004811015610d2a57610cff828960e001518360048110610281576102816154e5565b6102408701819052610d129084906117b2565b60a0860151610d22908390611645565b600101610cdc565b508351829084600d8110610d4057610d406154e5565b6020020181905250856101e00151846020015184600d8110610d6457610d646154e5565b602002015260c087015184516001949094019384600d8110610d8857610d886154e5565b6020020181905250856102200151846020015184600d8110610dac57610dac6154e5565b602002015261010087015184516001949094019384600d8110610dd157610dd16154e5565b6020020181905250856102400151846020015184600d8110610df557610df56154e5565b602002015250610160850151604084810180518201929092526101a0870151606080870180519093019190915261018088015183518201526101c0880151825190910152905160809081019290925261020090950151945101939093529392505050565b602081015151600003610e6b57600080fd5b610e756001611732565b608082018051919091526020808301805160408051808501825260008082529251815294518401949094529051835192830190935281529051815260025b6009811015610f02576020830151610ecc908390611645565b6040805160208101909152600081528251815283608001518260098110610ef557610ef56154e5565b6020020152600101610eb3565b505050565b610f0f6140a9565b602c8214610f1c57600080fd5b8367ffffffffffffffff811115610f3557610f35614788565b604051908082528060200260200182016040528015610f5e578160200160208202803683370190505b50815260005b84811015610fae57858582818110610f7e57610f7e6154e5565b9050602002013582600001518281518110610f9b57610f9b6154e5565b6020908102919091010152600101610f64565b506000805b600481101561102857610fff858584818110610fd157610fd16154e5565b905060200201358686610fe48660010190565b818110610ff357610ff36154e5565b905060200201356117c1565b83602001518260048110611015576110156154e5565b6020020152600282019150600101610fb3565b5061105184848381811061103e5761103e6154e5565b905060200201358585610fe48560010190565b604083015260020161106e84848381811061103e5761103e6154e5565b61016083015260020161108c84848381811061103e5761103e6154e5565b61018083015260020160005b60048110156110df576110b6858584818110610fd157610fd16154e5565b836060015182600481106110cc576110cc6154e5565b6020020152600282019150600101611098565b5060005b60048110156111345761110d858584818110611101576111016154e5565b90506020020135611732565b83608001518260048110611123576111236154e5565b6020020152600191820191016110e3565b5060005b600181101561117d57611156858584818110611101576111016154e5565b8360a00151826001811061116c5761116c6154e5565b602002015260019182019101611138565b5060005b60018110156111c65761119f858584818110611101576111016154e5565b8360c0015182600181106111b5576111b56154e5565b602002015260019182019101611181565b5060005b600381101561120f576111e8858584818110611101576111016154e5565b8360e0015182600381106111fe576111fe6154e5565b6020020152600191820191016111ca565b50611225848483818110611101576111016154e5565b610100830152600101611243848483818110611101576111016154e5565b6101a0830152600101611261848483818110611101576111016154e5565b6101c083015260010161127f848483818110611101576111016154e5565b6101e083015260010161129d848483818110611101576111016154e5565b6102008301526001016112bb848483818110611101576111016154e5565b6102208301526001016112d9848483818110611101576111016154e5565b6102408301526001016112f7848483818110611101576111016154e5565b610120830152600101611315848483818110611101576111016154e5565b61014083015260010161133384848381811061103e5761103e6154e5565b61026083015260020161135184848381811061103e5761103e6154e5565b61028083015250949350505050565b60008061136d8484611a37565b905061137a8385836127a8565b151560000361138d57600091505061163f565b60608401516000906113c690825b6020020151604080518082019091526000808252602080830191825283518352929092015190915290565b84516101808401519192506000916113dd91612ab3565b604080516020808201835260008083528451835283518085019094528084529083015291925060015b6004811015611450576114288960600151826004811061139b5761139b6154e5565b91506114348284612b44565b61143e85836117b2565b6114488385611645565b600101611406565b505050506000611461858785610af5565b8051839052610120870151602082015152905061147f858785612b4f565b815160209081019190915261014087015181830180519092015281515190515160006114ab6001611732565b90506114ca604051806040016040528060008152602001600081525090565b60015b600d811015611553576101408801516114e7908490611645565b61150183876000015183600d8110610281576102816154e5565b915061150d85836117b2565b856020015181600d8110611523576115236154e5565b6020020151610220890181905261153a9084611645565b61022088015161154b9085906116c7565b6001016114cd565b50610140870151611565908390611645565b6000611582838760400151600060068110610281576102816154e5565b6060870151519091506115958185611645565b60015b600681101561161e576101408a01516115b2908690611645565b6115cc8589604001518360068110610281576102816154e5565b93506115d883856117b2565b876060015181600681106115ee576115ee6154e5565b60200201516102208b018190526116059086611645565b6102208a01516116169083906116c7565b600101611598565b506116338b61014001518d8b89868a87612fa1565b99505050505050505050505b92915050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001815183510990915250565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181516116be907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001615543565b83510890915250565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001815183510890915250565b6040805180820190915260008082526020820152825115801561171a575082602001516001145b1561172757600060208401525b61163f83838361313c565b6040805160208101909152600081527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001821061176d57600080fd5b50604080516020810190915290815290565b60408051808201909152600080825260208201525b5060408051808201909152918252602082015290565b6117946142b7565b6117bd82828461317e565b5050565b6040805180820190915260008082526020820152821580156117e1575081155b1561180257604051806040016040528084815260200183815250905061163f565b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478310611890576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7820617869732069736e27742076616c6964000000000000000000000000000060448201526064015b60405180910390fd5b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478210611919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7920617869732069736e27742076616c696400000000000000000000000000006044820152606401611887565b60007f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47838409905060007f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4785860990507f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4785820990507f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47600382089050808214611a1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6973206e6f74206f6e20637572766500000000000000000000000000000000006044820152606401611887565b50506040805180820190915292835250602082015290565b611a3f6142d7565b60408051606081018252600080825260208201819052918101829052905b8360200151811015611aa157611a9985600001518281518110611a8257611a826154e5565b60200260200101518361320e90919063ffffffff16565b600101611a5d565b5060005b6004811015611beb57611be385602001518260048110611ac757611ac76154e5565b602002015183908051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a01949094528383018190528387019b909b52828a0181905284518084038b0181529284018552825192880192909220909a528451835180880198909852998701989098529185019790975283850195909552855180840390940184529190930190935280519101209052565b600101611aa5565b50611bf5816132f1565b60a08301526101608401518051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a01949094528383018190528387019b909b52828a0181905284518084038b01815292840185528251928801929092208b528551845180890199909952908801999099529286019790975284860191909152805180850390950185529290940190915281519101209052611d1b816132f1565b6040830152611d29816132f1565b6060830152604084810151805183516020808601805186516000818501819052602480830187905260448084019490945260648084018990528a518085038201815260849485018c528051908801208c5285518b517c0100000000000000000000000000000000000000000000000000000000818a018190528185019a909a5280870191909152808201999099528a51808a03820181529884018b52885198870198909820808652988601518b518b51808901949094528383018190528386019a909a528289018190528a518084038a0181529284018b528251928701929092208b5284518a5180880198909852908701989098529185019690965283850152855180840390940184529190930190935280519101209052611e4a816132f1565b60c0830152611e58816132f1565b60e08301526101808401518051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a01949094528383018190528387019b909b52828a0181905284518084038b01815292840185528251928801929092208b528551845180890199909952908801999099529286019790975284860191909152805180850390950185529290940190915281519101209052611f7e816132f1565b602083015260005b6004811015611fb057611fa885606001518260048110611ac757611ac76154e5565b600101611f86565b50611fba816132f1565b610180830152610120840151518151602080840180516040805160008186015260248082018790526044808301949094526064808301899052835180840382018152608493840185528051908801208a52855184517c0100000000000000000000000000000000000000000000000000000000818a015292830198909852938101969096528583019690965280518086039092018252939094019092528251920191909120905260005b60048110156121325761212a85608001518260048110612086576120866154e5565b6020908102919091015151845185830180516040805160008188015260248082018690526044808301949094526064808301889052835180840382018152608493840185528051908a01208c52855184517c0100000000000000000000000000000000000000000000000000000000818c01529283019790975293810195909552848301959095528051808503909201825292909301909152815191909201209052565b600101612064565b5060005b6001811015612160576121588560a001518260018110612086576120866154e5565b600101612136565b5060005b600181101561218e576121868560c001518260018110612086576120866154e5565b600101612164565b5060005b60038110156121bc576121b48560e001518260038110612086576120866154e5565b600101612192565b506101808201516040805160208101825260008152915182526101a084018290528401516121ea9190611645565b61010084015151815160208084018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208b52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b038201815299840185528951998801999099208087526101e08e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526102208e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526102408e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526101a08e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526101c08e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526102008e0151518b518651808b0186905280850182905280890193909352828c0182905286518084038d01815292860187528251928a01929092208c5287518651808b018c90528085019390935282880152818b015284518082038b01815290840185528051908801208087526101408e0151518b518651808b019590955284840181905284880192909252838b0181905285518085038c01815293850186528351938901939093208b5286518551808a019a909a5291890152938701939093528587019290925280518086039096018652930190925282519201919091209052612599816132f1565b6101408301526102608401518051825160208085018051604080516000818601819052602480830188905260448084019590955260648084018a9052845180850382018152608494850186528051908901208c52865185517c0100000000000000000000000000000000000000000000000000000000818b018190528185019b909b52808801919091528082019a909a528451808b03820181529984018552895199880199909920808752998701518b518551808a018590528084018290528088019c909c528b8b018290528551808d038c0181529b850186528b519b89019b909b208c5286518551808a018b90528084019c909c528b8701528a8a01528351808b038a01815299830184528951998701999099208086526102808e015180518c518651808b01869052808e0182905280890194909452838c0182905286518085038d01815293860187528351938a01939093208d5287518651808b018c9052808e019490945283880152828b015284518083038b0181529184018552815191880191909120808752908701518b518551808a0194909452838c0181905283870192909252828a0181905284518084038b01815292840185528251928801929092208b52855184518089019990995299880152928601979097528486019190915280518085039095018552929094019091528151910120905261279b816132f1565b6101608301525092915050565b600080846020015167ffffffffffffffff8111156127c8576127c8614788565b6040519080825280602002602001820160405280156127f1578160200160208202803683370190505b50905060005b81518110156128265780828281518110612813576128136154e5565b60209081029190910101526001016127f7565b50600085602001511161283857600080fd5b60006128446000611732565b905060005b86602001518110156128c25761286e81886000015189604001518861018001516133e1565b610220860152855180516128a99161289d9184908110612890576128906154e5565b6020026020010151611732565b61022087015190611645565b6102208501516128ba9083906116c7565b600101612849565b5060c08501516128db9060005b60200201518290611645565b610140850151604080516020810190915260008152905181526128fe81836116c7565b61290785610e59565b608085015160009061291a90600461017f565b90506129348761010001518261164590919063ffffffff16565b61294060016004615543565b60031461294c57600080fd5b60408051602081019091526000815260005b60038110156129e0576129808960e00151826003811061017f5761017f6154e5565b915061299988604001518361164590919063ffffffff16565b6129be896080015182600481106129b2576129b26154e5565b602002015183906116c7565b60608801516129ce9083906116c7565b6129d88383611645565b60010161295e565b5060808801516129f190600361017f565b9050612a0a8760600151826116c790919063ffffffff16565b612a148282611645565b612a1e8383611671565b6000612a338a6000015189610180015161348f565b6080890151909150612a469060056128cf565b612a508482611671565b6000612a5d8b8b8b613515565b9050612a6985826116c7565b6101208a0151604080516020810190915260008152905181528b516101808b0151612a9e91612a9791613765565b8290611645565b945194519094149a9950505050505050505050565b604080516020808201835260008252825160c0810184528181528082018290529283015283516060830152608082018390527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a083015290612b1461448b565b600060208260c08560055afa905080612b2c57600080fd5b50604080516020810190915290518152949350505050565b6117bd82828461313c565b6040805180820190915260008082526020820152612b6e60008061177f565b90506000612b9d8460800151600060048110612b8c57612b8c6154e5565b602002015160808701516000610281565b9050612ba982826117b2565b6080840151612bc5906001602002015160808701516001610281565b9050612bd182826117b2565b6080840151612bed906002602002015160808701516002610281565b9050612bf982826117b2565b6080840151612c15906003602002015160808701516003610281565b9050612c2182826117b2565b6080840151600090612c33908261017f565b6080860151909150612c469060016128cf565b6080860151612c589082906004610281565b9150612c6483836117b2565b6080850151612c7490600061017f565b6080860151909150612c879060026128cf565b6080860151612c999082906005610281565b9150612ca583836117b2565b608086015160c00151612cb99084906117b2565b60a0850151516080870151612cd091906007610281565b9150612cdc83836117b2565b60c085015151612ced908490612b44565b6000612cfa878787610141565b9050612d0684826117b2565b612d1260016004615543565b600314612d1e57600080fd5b6000612d2a6001611732565b90506000612d48876080015160046009811061017f5761017f6154e5565b905060005b6004811015612e105761018088015160408051602081019091526000815290518152945080600003612d8857612d838584611645565b612db9565b6101208a0151612db990612d9d600184615543565b60038110612dad57612dad6154e5565b60200201518690611645565b6040880151612dc9908690611645565b6060880151612dd99086906116c7565b612dfe89608001518260048110612df257612df26154e5565b602002015186906116c7565b612e088286611645565b600101612d4d565b506040880151612e2090826116f3565b9450612e2c86866117b2565b6080870151612e3c90600461017f565b9050612e5587604001518261164590919063ffffffff16565b610100880151612e66908290611645565b60005b612e7560016004615543565b811015612ee957612e958960e00151826003811061017f5761017f6154e5565b9450612eae88604001518661164590919063ffffffff16565b6060880151612ebe9086906116c7565b612ed789608001518260048110612df257612df26154e5565b612ee18286611645565b600101612e69565b5060a0890151612efc9082906003610281565b9450612f088686613794565b612f2260008a600001518b604001518a61018001516133e1565b6101e0880181905251600003612f3757600080fd5b506101e0860151604080516020810190915260008152905181526080870151612f619060056128cf565b6040880151612f7090826116f3565b9450612f7c86866117b2565b6000612f88898961379f565b9050612f9487826117b2565b5050505050509392505050565b60408051808201909152600080825260208083018281528751845290870151905290612fdb87610160015186612b4490919063ffffffff16565b612fe581866117b2565b60408051602081019091526000815283518152610160880151613009908290611645565b61301381866116c7565b600061304b82613045604080518082018252600080825260209182015281518083019092526001825260029082015290565b906116f3565b90506130578382613794565b6101808901516102608b015161306c916116f3565b9050600061308f8a6101a001516040805160208101909152600081529051815290565b90506130a98a61016001518261164590919063ffffffff16565b6102808b01516000906130bc90836116f3565b90506130c883826117b2565b6130d285846117b2565b60006130f18c61016001518e61028001516116f390919063ffffffff16565b905061310b8d6102600151826117b290919063ffffffff16565b61311481613a6d565b8d5160208f015161312788838584613abf565b98505050505050505050979650505050505050565b6131446144a9565b835181526020840151816001602002015282518160026020020152600060408360608460075afa90508061317757600080fd5b5050505050565b815115801561318f57506020820151155b156131a7578251815260209283015192019190915250565b82511580156131b857506020830151155b156131cd578151815260209182015191015250565b6131d56144c7565b8351815260208085015181830152835160408301528301518160035b6020020152600060408360808460065afa90508061317757600080fd5b815160208084015160405160009281019290925260248201839052604482015260648101839052608401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152918152815160209283012085528482015190517c01000000000000000000000000000000000000000000000000000000009281019290925260248201839052604482015260648101839052608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020918201209301929092525050565b604080516020810190915260008152815160208084015160408086015190517c0200000000000000000000000000000000000000000000000000000000938101939093526024830193909352604482015260e09190911b7fffffffff000000000000000000000000000000000000000000000000000000001660648201526000906068016040516020818303038152906040528051906020012090506001836040018181516133a09190615556565b63ffffffff1690525060408051602081019091527f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91909116815292915050565b6040805160208101909152600081528385106133fc57600080fd5b60006134086001611732565b905060006134168588612ab3565b90506134228487612ab3565b925061342e8383611671565b825160000361343c57600080fd5b6134468382611645565b604080516020810190915260008152845181526134638183611671565b61346f612a9788611732565b61347881613bbf565b90506134848482611645565b505050949350505050565b60408051602081019091526000815260006134aa6001611732565b905060006134b785611732565b604080516020810190915260008152855181529091506134d78184611671565b6134e18183611645565b6134ea81613bbf565b90506134f68587612ab3565b93506135028484611671565b61350c8482611645565b50505092915050565b604080516020810190915260008152604080516020810190915260008152600061353f6001611732565b905061355f8460c001516040805160208101909152600081529051815290565b610100850181905261357190826116c7565b61010084015160408051602081019091526000815290518152610120850181905260e08501516135a19190611645565b6101a08501516040805160208101909152600081529051815291506135d38460c001518361164590919063ffffffff16565b6101208401516135e49083906116c7565b6101c08501516135f5908390611645565b60808401516136059060066101ca565b60006136266001886000015161361b9190615543565b604089015190612ab3565b90506136478561018001516040805160208101909152600081529051815290565b6101c086018190526136599082611671565b6101c085015161366a908490611645565b61367484846116c7565b61368e6000886000015189604001518861018001516133e1565b6101e0860181905260408051602081019091526000815290518152608086015160e001519093506136c0908490611645565b6136ca8484611671565b60006136ec600189600001516136e09190615543565b61012088015190612ab3565b9050613714600189600001516137029190615543565b895160408b01516101808a01516133e1565b610200870181905260408051602081019091526000815290518152935061373b8482611645565b60808601516101000151613750908590611645565b61375a8585611671565b505050509392505050565b60408051602081019091526000815261377e8284612ab3565b905061163f61378d6001611732565b8290611671565b6117bd828284613c10565b604080518082019091526000808252602082015260006137bf6000611732565b90506137d76040518060200160405280600081525090565b60408051602080820183526000918290526101c0880151835191820190935290815290518152608085015161380d9060066128cf565b6101c085015161381e908290611645565b61016086015160009061383190836116f3565b905061383d85826117b2565b61020087015160408051602081019091526000815290518152915061386f8660c001518361164590919063ffffffff16565b6101e08701516138809083906116c7565b6101208601516138919083906116c7565b60408051602081019091526000815260006138ac6001611732565b90506138c46040518060200160405280600081525090565b60005b6138d360016004615543565b811015613921576138f38b60800151826004811061017f5761017f6154e5565b91506138ff8284611645565b61390984836116c7565b60a08a0151613919908490611645565b6001016138c7565b506102408a01516040805160208101909152600081529051815295506139478683611645565b61395183876116c7565b6102208a0151613962908490611645565b60e08901516139729084906116c7565b61397c8584611645565b61010089015161398d908690611645565b6040805160208101909152600081528751815295506139ac8686611671565b60808901518695506139bf906006612dad565b6101c08901516139d0908690611645565b6101e08901516040805160208101909152600081529051815260808a0151909650613a049060075b60200201518790611645565b613a0e85876116c7565b6102008901516040805160208101909152600081529051815260808a0151909650613a3a9060086139f8565b613a4485876116c7565b6101808a0151613a5490866116f3565b9350613a6088856117b2565b5050505050505092915050565b8060200151600003613a8857805115613a8557600080fd5b50565b6020810151613ab7907f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47615543565b602090910152565b60408051600280825260608201909252600091829190816020015b6040805180820190915260008082526020820152815260200190600190039081613ada5750506040805160028082526060820190925291925060009190602082015b613b246142b7565b815260200190600190039081613b1c5790505090508682600081518110613b4d57613b4d6154e5565b60200260200101819052508482600181518110613b6c57613b6c6154e5565b60200260200101819052508581600081518110613b8b57613b8b6154e5565b60200260200101819052508381600181518110613baa57613baa6154e5565b60200260200101819052506101368282613cde565b6040805160208101909152600081528151600003613bdc57600080fd5b61163f82613c0b60027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001615543565b612ab3565b8151158015613c2157506020820151155b15613c39578251815260209283015192019190915250565b8251158015613c4a57506020830151155b15613c8c57815181526020820151613c82907f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47615543565b6020909101525050565b613c946144c7565b835181526020808501518183015283516040830152830151613cd6907f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47615543565b8160036131f1565b60008151835114613cee57600080fd5b82516000613cfd826006615573565b905060008167ffffffffffffffff811115613d1a57613d1a614788565b604051908082528060200260200182016040528015613d43578160200160208202803683370190505b50905060005b83811015613f7457868181518110613d6357613d636154e5565b60200260200101516000015182826006613d7d9190615573565b613d8890600061558a565b81518110613d9857613d986154e5565b602002602001018181525050868181518110613db657613db66154e5565b60200260200101516020015182826006613dd09190615573565b613ddb90600161558a565b81518110613deb57613deb6154e5565b602002602001018181525050858181518110613e0957613e096154e5565b6020908102919091010151515182613e22836006615573565b613e2d90600261558a565b81518110613e3d57613e3d6154e5565b602002602001018181525050858181518110613e5b57613e5b6154e5565b60209081029190910181015151015182613e76836006615573565b613e8190600361558a565b81518110613e9157613e916154e5565b602002602001018181525050858181518110613eaf57613eaf6154e5565b602002602001015160200151600060028110613ecd57613ecd6154e5565b602002015182613ede836006615573565b613ee990600461558a565b81518110613ef957613ef96154e5565b602002602001018181525050858181518110613f1757613f176154e5565b602002602001015160200151600160028110613f3557613f356154e5565b602002015182613f46836006615573565b613f5190600561558a565b81518110613f6157613f616154e5565b6020908102919091010152600101613d49565b50613f7d61448b565b6000602082602086026020860160085afa905080613f9a57600080fd5b505115159695505050505050565b6040518061016001604052806000815260200160008152602001613fd86040518060200160405280600081525090565b8152602001613fe56144e5565b8152602001613ff261451e565b8152602001613fff61454a565b8152602001614021604051806040016040528060008152602001600081525090565b815260200161402e61454a565b8152602001614050604051806040016040528060008152602001600081525090565b815260200161405d614573565b815260200161406a6145a7565b905290565b60405180608001604052806140826145d4565b815260200161408f614600565b815260200161409c614623565b815260200161406a61464d565b604051806102a00160405280606081526020016140c461454a565b81526020016140e6604051806040016040528060008152602001600081525090565b81526020016140f361454a565b815260200161410061466e565b8152604080518082018252600060208083018281528352808501929092528251808401845291820190815281529082015260600161413c614573565b81526020016141576040518060200160405280600081525090565b81526020016141726040518060200160405280600081525090565b815260200161418d6040518060200160405280600081525090565b81526020016141af604051806040016040528060008152602001600081525090565b81526020016141d1604051806040016040528060008152602001600081525090565b81526020016141ec6040518060200160405280600081525090565b81526020016142076040518060200160405280600081525090565b81526020016142226040518060200160405280600081525090565b815260200161423d6040518060200160405280600081525090565b81526020016142586040518060200160405280600081525090565b81526020016142736040518060200160405280600081525090565b8152602001614295604051806040016040528060008152602001600081525090565b815260200161406a604051806040016040528060008152602001600081525090565b60405180604001604052806142ca61468f565b815260200161406a61468f565b604080516102808101825260006102608201818152825282516020808201855282825280840191909152835180820185528281528385015283519081019093528252906060820190815260200161432c6146ad565b81526020016143476040518060200160405280600081525090565b81526020016143626040518060200160405280600081525090565b815260200161437d6040518060200160405280600081525090565b81526020016143986040518060200160405280600081525090565b81526020016143b36040518060200160405280600081525090565b81526020016143ce6040518060200160405280600081525090565b81526020016143e96040518060200160405280600081525090565b81526020016144046040518060200160405280600081525090565b815260200161441f6040518060200160405280600081525090565b815260200161443a6040518060200160405280600081525090565b81526020016144556040518060200160405280600081525090565b81526020016144706040518060200160405280600081525090565b81526020016142956040518060200160405280600081525090565b60405180602001604052806001906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b60405180604001604052806002905b60408051808201909152600080825260208201528152602001906001900390816144f45790505090565b6040805161014081019091526000610100820181815261012083019190915281526007602082016144f4565b6040805160c0810190915260006080820181815260a083019190915281526003602082016144f4565b60405180606001604052806003905b6040805160208101909152600081528152602001906001900390816145825790505090565b60405180604001604052806002905b6145be6142b7565b8152602001906001900390816145b65790505090565b604080516101e0810190915260006101a082018181526101c08301919091528152600c602082016144f4565b604080516101c0810190915260006101a082019081528152600c60208201614582565b604080516101008101909152600060c0820181815260e083019190915281526005602082016144f4565b6040805160e08101909152600060c082019081528152600560208201614582565b6040805160a081019091526000608082019081528152600360208201614582565b60405180604001604052806002906020820280368337509192915050565b604080516101408101909152600061012082019081528152600860208201614582565b60008083601f8401126146e257600080fd5b50813567ffffffffffffffff8111156146fa57600080fd5b6020830191508360208260051b850101111561471557600080fd5b9250929050565b6000806000806040858703121561473257600080fd5b843567ffffffffffffffff8082111561474a57600080fd5b614756888389016146d0565b9096509450602087013591508082111561476f57600080fd5b5061477c878288016146d0565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156147da576147da614788565b60405290565b6040516102a0810167ffffffffffffffff811182821017156147da576147da614788565b604051610260810167ffffffffffffffff811182821017156147da576147da614788565b604051610160810167ffffffffffffffff811182821017156147da576147da614788565b6040516080810167ffffffffffffffff811182821017156147da576147da614788565b60006020828403121561488157600080fd5b6040516020810181811067ffffffffffffffff821117156148a4576148a4614788565b6040529135825250919050565b6000604082840312156148c357600080fd5b6148cb6147b7565b9050813581526020820135602082015292915050565b600082601f8301126148f257600080fd5b6148fa6147b7565b80608084018581111561490c57600080fd5b845b818110156149305761492087826148b1565b845260209093019260400161490e565b509095945050505050565b600082601f83011261494c57600080fd5b60408051610100810181811067ffffffffffffffff8211171561497157614971614788565b82528061020085018681111561498657600080fd5b855b818110156149a95761499a88826148b1565b83526020909201918401614988565b50919695505050505050565b600082601f8301126149c657600080fd5b6149ce61484c565b806101008401858111156149e157600080fd5b845b81811015614930576149f587826148b1565b84526020909301926040016149e3565b600082601f830112614a1657600080fd5b6040516060810181811067ffffffffffffffff82111715614a3957614a39614788565b604052806060840185811115614a4e57600080fd5b845b81811015614a7057614a62878261486f565b835260209283019201614a50565b509195945050505050565b600082601f830112614a8c57600080fd5b614a946147b7565b806040840185811115614aa657600080fd5b845b81811015614930578035845260209384019301614aa8565b600082601f830112614ad157600080fd5b614ad96147b7565b80610100840185811115614aec57600080fd5b845b818110156149305760808188031215614b075760008081fd5b614b0f6147b7565b614b198883614a7b565b8152614b288860408401614a7b565b6020828101919091529085529390930192608001614aee565b600082601f830112614b5257600080fd5b8135602067ffffffffffffffff80831115614b6f57614b6f614788565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108482111715614bb257614bb2614788565b604052938452858101830193838101925087851115614bd057600080fd5b83870191505b8482101561013657813583529183019190830190614bd6565b600082601f830112614c0057600080fd5b614c0861484c565b806080840185811115614c1a57600080fd5b845b8181101561493057614c2e878261486f565b845260209384019301614c1c565b600082601f830112614c4d57600080fd5b604051602080820182811067ffffffffffffffff82111715614c7157614c71614788565b6040528184820186811115614c8557600080fd5b855b81811015614ca657614c99888261486f565b8352918301918301614c87565b50929695505050505050565b60006105a08284031215614cc557600080fd5b614ccd6147e0565b9050813567ffffffffffffffff811115614ce657600080fd5b614cf284828501614b41565b825250614d0283602084016149b5565b6020820152610120614d16848285016148b1565b6040830152610160614d2a858286016149b5565b6060840152610260614d3e86828701614bef565b6080850152614d51866102e08701614c3c565b60a0850152614d64866103008701614c3c565b60c0850152614d77866103208701614a05565b60e0850152614d8a86610380870161486f565b610100850152614d9e866103a0870161486f565b83850152614db0866103c0870161486f565b610140850152614dc4866103e087016148b1565b82850152614dd68661042087016148b1565b610180850152614dea86610460870161486f565b6101a0850152614dfe86610480870161486f565b6101c0850152614e12866104a0870161486f565b6101e0850152614e26866104c0870161486f565b610200850152614e3a866104e0870161486f565b610220850152614e4e86610500870161486f565b610240850152614e628661052087016148b1565b81850152505050614e778361056084016148b1565b61028082015292915050565b600082601f830112614e9457600080fd5b60405161012080820182811067ffffffffffffffff82111715614eb957614eb9614788565b60405283018185821115614ecc57600080fd5b845b82811015614a7057614ee0878261486f565b825260209182019101614ece565b60006103808284031215614f0157600080fd5b614f09614804565b9050614f15838361486f565b8152614f24836020840161486f565b6020820152614f36836040840161486f565b6040820152614f48836060840161486f565b6060820152614f5a8360808401614e83565b60808201526101a0614f6e8482850161486f565b60a08301526101c0614f828582860161486f565b60c08401526101e0614f968682870161486f565b60e0850152610200614faa8782880161486f565b610100860152610220614fbf8882890161486f565b610120870152610240614fd489828a0161486f565b610140880152614fe8896102608a0161486f565b610160880152614ffc896102808a0161486f565b610180880152615010896102a08a0161486f565b86880152615022896102c08a0161486f565b85880152615034896102e08a0161486f565b84880152615046896103008a0161486f565b83880152615058896103208a0161486f565b8288015261506a896103408a016148b1565b8188015250505050505092915050565b6000806000838503610a6081121561509157600080fd5b6106c0808212156150a157600080fd5b6150a9614828565b915085358252602086013560208301526150c6876040880161486f565b60408301526150d887606088016148e1565b60608301526150ea8760e0880161493b565b60808301526150fd876102e088016149b5565b60a0830152615110876103e088016148b1565b60c08301526151238761042088016149b5565b60e08301526151368761052088016148b1565b61010083015261514a876105608801614a05565b61012083015261515e876105c08801614ac0565b61014083015290935084013567ffffffffffffffff81111561517f57600080fd5b61518b86828701614cb2565b92505061519c856106e08601614eee565b90509250925092565b81518152602080830151908201526040810161163f565b8060005b60028110156151f4576151de84835180518252602090810151910152565b60409390930192602091909101906001016151c0565b50505050565b8060005b60088110156151f45761521c84835180518252602090810151910152565b60409390930192602091909101906001016151fe565b8060005b60048110156151f45761525484835180518252602090810151910152565b6040939093019260209190910190600101615236565b8060005b60038110156151f45781515184526020938401939091019060010161526e565b8060005b60028110156151f4578151845260209384019390910190600101615292565b8060005b60028110156151f45781516152cb85825161528e565b602090810151906152df604087018361528e565b608095909501949290920191506001016152b5565b60006106c0820190508251825260208301516020830152604083015161531d6040840182519052565b50606083015161533060608401826151bc565b50608083015161534360e08401826151fa565b5060a08301516153576102e0840182615232565b5060c083015180516103e08401526020015161040083015260e0830151615382610420840182615232565b506101008301518051610520840152602001516105408301526101208301516153af61056084018261526a565b506101408301516153c46105c08401826152b1565b5092915050565b8060005b60068110156151f4576153ed84835180518252602090810151910152565b60409390930192602091909101906001016153cf565b8060005b60068110156151f457815151845260209384019390910190600101615407565b81516107208201908260005b600d8110156154675761545182845180518252602090810151910152565b6020929092019160409190910190600101615433565b505050602080840151610340840160005b600d8110156154965782515182529183019190830190600101615478565b5050505060408301516154ad6104e08401826153cb565b5060608301516153c4610660840182615403565b600061038082840312156154d457600080fd5b6154de8383614eee565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561163f5761163f615514565b63ffffffff8181168382160190808211156153c4576153c4615514565b808202811582820484141761163f5761163f615514565b8082018082111561163f5761163f61551456fea2646970667358221220d2f17e9a0c25b77d7be3c1b56c33d3a035f0c73e0cf8dea1efb788c1f63f7bb364736f6c63430008110033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.