ETH Price: $1,967.39 (-2.02%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Verify Proof And...167685872023-03-06 10:01:35745 days ago1678096895IN
0x6cB3EE90...B91361BF6
0 ETH0.0505543132.64523862
Verify Proof And...167684932023-03-06 9:41:47745 days ago1678095707IN
0x6cB3EE90...B91361BF6
0 ETH0.0388995423.73298066

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GpsStatementVerifier

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion, Apache-2.0 license
File 1 of 12 : GpsStatementVerifier.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "CairoBootloaderProgram.sol";
import "CairoVerifierContract.sol";
import "MemoryPageFactRegistry.sol";
import "Identity.sol";
import "PrimeFieldElement0.sol";
import "GpsOutputParser.sol";

contract GpsStatementVerifier is
    GpsOutputParser,
    Identity,
    CairoBootloaderProgramSize,
    PrimeFieldElement0
{
    CairoBootloaderProgram bootloaderProgramContractAddress;
    MemoryPageFactRegistry memoryPageFactRegistry;
    CairoVerifierContract[] cairoVerifierContractAddresses;

    uint256 internal constant N_BUILTINS = 8;
    uint256 internal constant N_MAIN_ARGS = N_BUILTINS;
    uint256 internal constant N_MAIN_RETURN_VALUES = N_BUILTINS;
    // Cairo verifier program hash.
    uint256 immutable hashedSupportedCairoVerifiers_;
    // Simple bootloader program hash.
    uint256 immutable simpleBootloaderProgramHash_;

    /*
      Constructs an instance of GpsStatementVerifier.
      bootloaderProgramContract is the address of the bootloader program contract
      and cairoVerifierContracts is a list of cairoVerifiers indexed by their id.
    */
    constructor(
        address bootloaderProgramContract,
        address memoryPageFactRegistry_,
        address[] memory cairoVerifierContracts,
        uint256 hashedSupportedCairoVerifiers,
        uint256 simpleBootloaderProgramHash
    ) public {
        bootloaderProgramContractAddress = CairoBootloaderProgram(bootloaderProgramContract);
        memoryPageFactRegistry = MemoryPageFactRegistry(memoryPageFactRegistry_);
        cairoVerifierContractAddresses = new CairoVerifierContract[](cairoVerifierContracts.length);
        for (uint256 i = 0; i < cairoVerifierContracts.length; ++i) {
            cairoVerifierContractAddresses[i] = CairoVerifierContract(cairoVerifierContracts[i]);
        }
        hashedSupportedCairoVerifiers_ = hashedSupportedCairoVerifiers;
        simpleBootloaderProgramHash_ = simpleBootloaderProgramHash;
    }

    function identify() external pure override returns (string memory) {
        return "StarkWare_GpsStatementVerifier_2022_7";
    }

    /*
      Returns the bootloader config.
    */
    function getBootloaderConfig() external view returns (uint256, uint256) {
        return (simpleBootloaderProgramHash_, hashedSupportedCairoVerifiers_);
    }

    /*
      Verifies a proof and registers the corresponding facts.
      For the structure of cairoAuxInput, see cpu/CpuPublicInputOffsets.sol.
      taskMetadata is structured as follows:
      1. Number of tasks.
      2. For each task:
         1. Task output size (including program hash and size).
         2. Program hash.
    */
    function verifyProofAndRegister(
        uint256[] calldata proofParams,
        uint256[] calldata proof,
        uint256[] calldata taskMetadata,
        uint256[] calldata cairoAuxInput,
        uint256 cairoVerifierId
    ) external {
        require(
            cairoVerifierId < cairoVerifierContractAddresses.length,
            "cairoVerifierId is out of range."
        );
        CairoVerifierContract cairoVerifier = cairoVerifierContractAddresses[cairoVerifierId];

        // The values z and alpha are used only for the fact registration of the main page.
        // They are not part of the public input of CpuVerifier as they are computed there.
        // Take the relevant slice from 'cairoAuxInput'.
        uint256[] calldata cairoPublicInput = (
            cairoAuxInput[:cairoAuxInput.length -
                // z and alpha.
                2]
        );

        uint256[] memory publicMemoryPages;
        {
            (uint256 publicMemoryOffset, uint256 selectedBuiltins) = cairoVerifier.getLayoutInfo();

            require(cairoAuxInput.length > publicMemoryOffset, "Invalid cairoAuxInput length.");
            publicMemoryPages = (uint256[])(cairoPublicInput[publicMemoryOffset:]);
            uint256 nPages = publicMemoryPages[0];
            require(nPages < 10000, "Invalid nPages.");

            // Validate publicMemoryPages.length.
            // Each page has a page info and a cumulative product.
            // There is no 'page address' in the page info for page 0, but this 'free' slot is
            // used to store the number of pages.
            require(
                publicMemoryPages.length == nPages * (PAGE_INFO_SIZE + 1),
                "Invalid publicMemoryPages length."
            );

            // Process public memory.
            (
                uint256 publicMemoryLength,
                uint256 memoryHash,
                uint256 prod
            ) = registerPublicMemoryMainPage(taskMetadata, cairoAuxInput, selectedBuiltins);

            // Make sure the first page is valid.
            // If the size or the hash are invalid, it may indicate that there is a mismatch
            // between the prover and the verifier on the bootloader program or bootloader config.
            require(
                publicMemoryPages[PAGE_INFO_SIZE_OFFSET] == publicMemoryLength,
                "Invalid size for memory page 0."
            );
            require(
                publicMemoryPages[PAGE_INFO_HASH_OFFSET] == memoryHash,
                "Invalid hash for memory page 0."
            );
            require(
                publicMemoryPages[nPages * PAGE_INFO_SIZE] == prod,
                "Invalid cumulative product for memory page 0."
            );
        }

        // NOLINTNEXTLINE: reentrancy-benign.
        cairoVerifier.verifyProofExternal(proofParams, proof, (uint256[])(cairoPublicInput));

        registerGpsFacts(taskMetadata, publicMemoryPages, cairoAuxInput[OFFSET_OUTPUT_BEGIN_ADDR]);
    }

    /*
      Registers the fact for memory page 0, which includes:
      1. The bootloader program,
      2. Arguments and return values of main()
      3. Some of the data required for computing the task facts. which is represented in
         taskMetadata.
      Returns information on the registered fact.

      Arguments:
        selectedBuiltins: A bit-map of builtins that are present in the layout.
            See CairoVerifierContract.sol for more information.
        taskMetadata: Per task metadata.
        cairoAuxInput: Auxiliary input for the cairo verifier.

      Assumptions: cairoAuxInput is connected to the public input, which is verified by
      cairoVerifierContractAddresses.
      Guarantees: taskMetadata is consistent with the public memory, with some sanity checks.
    */
    function registerPublicMemoryMainPage(
        uint256[] calldata taskMetadata,
        uint256[] calldata cairoAuxInput,
        uint256 selectedBuiltins
    )
        private
        returns (
            uint256 publicMemoryLength,
            uint256 memoryHash,
            uint256 prod
        )
    {
        uint256 nTasks = taskMetadata[0];
        // Ensure 'nTasks' is bounded as a sanity check (the bound is somewhat arbitrary).
        require(nTasks < 2**30, "Invalid number of tasks.");

        // Public memory length.
        publicMemoryLength = (PROGRAM_SIZE +
            // return fp and pc =
            2 +
            N_MAIN_ARGS +
            N_MAIN_RETURN_VALUES +
            // Bootloader config size =
            2 +
            // Number of tasks cell =
            1 +
            2 *
            nTasks);
        uint256[] memory publicMemory = new uint256[](MEMORY_PAIR_SIZE * publicMemoryLength);

        uint256 offset = 0;

        // Write public memory, which is a list of pairs (address, value).
        {
            // Program segment.
            uint256[PROGRAM_SIZE] memory bootloaderProgram = bootloaderProgramContractAddress
                .getCompiledProgram();
            for (uint256 i = 0; i < bootloaderProgram.length; i++) {
                // Force that memory[i + INITIAL_PC] = bootloaderProgram[i].
                publicMemory[offset] = i + INITIAL_PC;
                publicMemory[offset + 1] = bootloaderProgram[i];
                offset += 2;
            }
        }

        {
            // Execution segment - Make sure [initial_fp - 2] = initial_fp and .
            // This is required for the "safe call" feature (that is, all "call" instructions will
            // return, even if the called function is malicious).
            // It guarantees that it's not possible to create a cycle in the call stack.
            uint256 initialFp = cairoAuxInput[OFFSET_EXECUTION_BEGIN_ADDR];
            require(initialFp >= 2, "Invalid execution begin address.");
            publicMemory[offset + 0] = initialFp - 2;
            publicMemory[offset + 1] = initialFp;
            // Make sure [initial_fp - 1] = 0.
            publicMemory[offset + 2] = initialFp - 1;
            publicMemory[offset + 3] = 0;
            offset += 4;

            // Execution segment: Enforce main's arguments and return values.
            // Note that the page hash depends on the order of the (address, value) pair in the
            // publicMemory and consequently the arguments must be written before the return values.
            uint256 returnValuesAddress = cairoAuxInput[OFFSET_EXECUTION_STOP_PTR] - N_BUILTINS;
            uint256 builtinSegmentInfoOffset = OFFSET_OUTPUT_BEGIN_ADDR;

            for (uint256 i = 0; i < N_BUILTINS; i++) {
                // Write argument address.
                publicMemory[offset] = initialFp + i;
                uint256 returnValueOffset = offset + 2 * N_BUILTINS;

                // Write return value address.
                publicMemory[returnValueOffset] = returnValuesAddress + i;

                // Write values.
                if ((selectedBuiltins & 1) != 0) {
                    // Set the argument to the builtin start pointer.
                    publicMemory[offset + 1] = cairoAuxInput[builtinSegmentInfoOffset];
                    // Set the return value to the builtin stop pointer.
                    publicMemory[returnValueOffset + 1] = cairoAuxInput[
                        builtinSegmentInfoOffset + 1
                    ];
                    builtinSegmentInfoOffset += 2;
                } else {
                    // Builtin is not present in layout, set the argument value and return value to 0.
                    publicMemory[offset + 1] = 0;
                    publicMemory[returnValueOffset + 1] = 0;
                }
                offset += 2;
                selectedBuiltins >>= 1;
            }
            require(selectedBuiltins == 0, "SELECTED_BUILTINS_VECTOR_IS_TOO_LONG");
            // Skip the return values which were already written.
            offset += 2 * N_BUILTINS;
        }

        // Program output.
        {
            {
                uint256 outputAddress = cairoAuxInput[OFFSET_OUTPUT_BEGIN_ADDR];
                // Force that memory[outputAddress] and memory[outputAddress + 1] contain the
                // bootloader config (which is 2 words size).
                publicMemory[offset + 0] = outputAddress;
                publicMemory[offset + 1] = simpleBootloaderProgramHash_;
                publicMemory[offset + 2] = outputAddress + 1;
                publicMemory[offset + 3] = hashedSupportedCairoVerifiers_;
                // Force that memory[outputAddress + 2] = nTasks.
                publicMemory[offset + 4] = outputAddress + 2;
                publicMemory[offset + 5] = nTasks;
                offset += 6;
                outputAddress += 3;

                uint256[] calldata taskMetadataSlice = taskMetadata[METADATA_TASKS_OFFSET:];
                for (uint256 task = 0; task < nTasks; task++) {
                    uint256 outputSize = taskMetadataSlice[METADATA_OFFSET_TASK_OUTPUT_SIZE];

                    // Ensure 'outputSize' is at least 2 and bounded from above as a sanity check
                    // (the bound is somewhat arbitrary).
                    require(2 <= outputSize && outputSize < 2**30, "Invalid task output size.");
                    uint256 programHash = taskMetadataSlice[METADATA_OFFSET_TASK_PROGRAM_HASH];
                    uint256 nTreePairs = taskMetadataSlice[METADATA_OFFSET_TASK_N_TREE_PAIRS];

                    // Ensure 'nTreePairs' is at least 1 and bounded from above as a sanity check
                    // (the bound is somewhat arbitrary).
                    require(
                        1 <= nTreePairs && nTreePairs < 2**20,
                        "Invalid number of pairs in the Merkle tree structure."
                    );
                    // Force that memory[outputAddress] = outputSize.
                    publicMemory[offset + 0] = outputAddress;
                    publicMemory[offset + 1] = outputSize;
                    // Force that memory[outputAddress + 1] = programHash.
                    publicMemory[offset + 2] = outputAddress + 1;
                    publicMemory[offset + 3] = programHash;
                    offset += 4;
                    outputAddress += outputSize;
                    taskMetadataSlice = taskMetadataSlice[METADATA_TASK_HEADER_SIZE +
                        2 *
                        nTreePairs:];
                }
                require(taskMetadataSlice.length == 0, "Invalid length of taskMetadata.");

                require(
                    cairoAuxInput[OFFSET_OUTPUT_STOP_PTR] == outputAddress,
                    "Inconsistent program output length."
                );
            }
        }

        require(publicMemory.length == offset, "Not all Cairo public inputs were written.");

        uint256 z = cairoAuxInput[cairoAuxInput.length - 2];
        uint256 alpha = cairoAuxInput[cairoAuxInput.length - 1];
        bytes32 factHash;
        (factHash, memoryHash, prod) = memoryPageFactRegistry.registerRegularMemoryPage(
            publicMemory,
            z,
            alpha,
            K_MODULUS
        );
    }
}

File 2 of 12 : CairoBootloaderProgram.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// ---------- The following code was auto-generated. PLEASE DO NOT EDIT. ----------
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

contract CairoBootloaderProgramSize {
    uint256 internal constant PROGRAM_SIZE = 562;
}

contract CairoBootloaderProgram is CairoBootloaderProgramSize {
    function getCompiledProgram()
        external pure
        returns (uint256[PROGRAM_SIZE] memory)
    {
        return [
            290341444919459839,
            8,
            1226245742482522112,
            386,
            74168662805676031,
            0,
            2345108766317314046,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            5198420613823102976,
            3618502788666131213697322783095070105623107215331596699973092056135872020479,
            2345108766317314046,
            146226256843603965,
            4,
            5191102238658887680,
            2345108766317314046,
            290341444919459839,
            3,
            4632937381316558848,
            4612671182992932865,
            4612671182992998402,
            146226256843603968,
            4,
            74168662805676031,
            4,
            4612671182993063937,
            4612671182993129474,
            5198983563776196608,
            1,
            5198983563776262144,
            1,
            5200109459388203008,
            5200109459388268544,
            5198983563776458752,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020458,
            2345108766317314046,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020449,
            5191102234363920384,
            5191102238658887680,
            5191102242953854976,
            5198420613822906368,
            90,
            5189976364521848832,
            8,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020446,
            4623648689905041407,
            291467327646433279,
            2345108766317314046,
            5199827962936983548,
            5208553695804948479,
            4612389708016287743,
            5198983563776262144,
            1,
            2345108766317314046,
            146226256843603965,
            4,
            5191102230068953088,
            2345108766317314046,
            5191102230068953088,
            5188850460319711232,
            5188850460319776768,
            5188850460319842304,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020467,
            5198983563776262144,
            1,
            5198983563776327680,
            1,
            5198983563776393216,
            1,
            5198983563776458752,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020463,
            2345108766317314046,
            5188850460319907840,
            5202361254907052032,
            5191102242953854976,
            5188287510366552064,
            5188287506071519232,
            5188287510366486527,
            4611826762357964797,
            5198420613822906368,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            5198420613822906368,
            3,
            5188287518956224512,
            4623085744246521853,
            145944781866893308,
            3618502788666131213697322783095070105623107215331596699973092056135872020472,
            2345108766317314046,
            290341444919459839,
            24,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020390,
            4617174774030761984,
            4612671182992998402,
            5189976364521848832,
            0,
            4612389712311713791,
            5188850464614678528,
            5191102264428691456,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020454,
            4612389712311779327,
            4622804286450008067,
            4,
            4612671195878359044,
            5200109476568596480,
            5188850468910104576,
            4625619027626983429,
            4622804286450073606,
            2,
            4617174765440827399,
            4612671191582933000,
            4612671195877900297,
            4612671200172867594,
            4612671204467834891,
            4612671208762802188,
            4612671213057769485,
            5191102242953854976,
            5198983563776655360,
            6,
            5191102273018626048,
            5191102277313593344,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020390,
            1191342862550269952,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020356,
            4623648724265893887,
            5191102242953854976,
            5198983563776655360,
            15,
            5191102273018626048,
            5191102320263266304,
            5189976364521848832,
            8,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020351,
            4623648719970271231,
            5191102238658887680,
            5198983563776655360,
            6,
            5198983563776655360,
            15,
            5191102247248822272,
            5189976364521848832,
            8,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020386,
            4623930190653259791,
            4612671182993522711,
            5198983563776655360,
            15,
            5193354051357474816,
            2345108766317314046,
            290341444919459839,
            26,
            4622804286449287169,
            1,
            4614922944152305666,
            4614922982807011331,
            4614922952742240260,
            4614922957037207557,
            4614922961332174854,
            4614922965627142151,
            4614922969922109448,
            4613797087195136009,
            122550255383924,
            4613797087195136010,
            8098989891770344814,
            4613797087195136011,
            138277649577220228665140075,
            4613797087195136012,
            435459224417,
            4613797087195136013,
            27700496658166629,
            4613797087195136014,
            435458895728,
            4613797087195136015,
            118083203326315,
            4613797087195136016,
            8101821134059892590,
            4613797087195136017,
            1,
            4613797087195136018,
            3,
            4613797087195136019,
            1,
            4613797087195136020,
            2,
            4613797087195136021,
            5,
            4613797087195136022,
            7,
            4613797087195136023,
            16,
            4613797087195136024,
            6,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020283,
            5198420613823102976,
            1,
            5191102225773985792,
            5198420613822971904,
            9,
            5198420613822906368,
            17,
            5188850460319449088,
            1226245742482522112,
            35,
            4614641507830300671,
            4617174774030762009,
            5188850468911677440,
            5201798300658860031,
            5189976364521848832,
            64,
            1226245742482522112,
            11,
            5188850460321742848,
            5188850464616710144,
            5188850468911677440,
            5188850473206644736,
            5188850477501612032,
            5188850481796579328,
            5188850486091546624,
            5188850490386513920,
            2345108766317314046,
            146226256843603965,
            5,
            4613797087195135996,
            0,
            2345108766317314046,
            290341444919459839,
            1,
            5201798304953761792,
            5202079779930537980,
            4634344751905079295,
            5193354047062507520,
            5198983563776458752,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020468,
            2345108766317314046,
            146226256843603965,
            5,
            5191102230068953088,
            5191102234363920384,
            2345108766317314046,
            5191102230068953088,
            5191102234363920384,
            5191102238658887680,
            5191102242953854976,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020318,
            5191102238658887680,
            5191102242953854976,
            5198983563776458752,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020466,
            2345108766317314046,
            4612671182993129469,
            5198983563776393216,
            1,
            2345108766317314046,
            5191102238658887680,
            5199827967231950845,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020475,
            2345108766317314046,
            5191102238658887680,
            5191102242953854976,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020470,
            5191102242953854976,
            5191102247248822272,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020470,
            2345108766317314046,
            290341444919459839,
            1,
            5191102230068953088,
            5191102260133724160,
            5198983563776393216,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020466,
            5209116658642944000,
            5202361254906855424,
            4612108233039904765,
            5193354047062507520,
            5193354051357474816,
            2345108766317314046,
            4612671182993063932,
            4612671187288031229,
            5198983563776327680,
            3,
            5188850468909711360,
            2345108766317314046,
            290341444919459839,
            2,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020180,
            4613797087195136000,
            0,
            4613797087195136001,
            0,
            5193354051357474816,
            2345108766317314046,
            290341444919459839,
            2,
            5191102234363920384,
            5191102242953854976,
            5191102247248822272,
            5188850460319776768,
            1226245742482522112,
            16,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020164,
            4617174769735794688,
            5188850464614744064,
            4623367219223429121,
            5193354038472572928,
            5193354042767540224,
            2345108766317314046,
            5191102242953854976,
            5188850460319907840,
            5188850464614875136,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020446,
            2345108766317314046,
            146226256843603964,
            5,
            5191102234363920384,
            5191102247248822272,
            2345108766317314046,
            290341444919459839,
            1,
            5198983563776393216,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            4626181977580208128,
            5191102238658887680,
            5191102234363920384,
            5191102247248822272,
            5202079771340603392,
            4611826758063063038,
            5188287510366420992,
            4611826762357964799,
            5198420613822906368,
            1,
            5198420613822906368,
            3,
            5188287518956224512,
            145944781866893307,
            3618502788666131213697322783095070105623107215331596699973092056135872020472,
            2345108766317314046,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020424,
            5191102238658887680,
            5193354051357474816,
            5191102242953854976,
            5191102247248822272,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020428,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020442,
            2345108766317314046,
            146226256843603965,
            3,
            2345108766317314046,
            5191102238658887680,
            5191102242953854976,
            5188287510366617600,
            4611826758063063039,
            5198420613823037441,
            1,
            5198420613823037441,
            1,
            722405534170316798,
            3618502788666131213697322783095070105623107215331596699973092056135872020475,
            4623648689905041407,
            2345108766317314046,
            290341444919459839,
            10,
            5191102260133724160,
            5191102221479018496,
            5191102225773985792,
            5191102230068953088,
            5191102234363920384,
            5191102238658887680,
            5191102242953854976,
            5191102247248822272,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020244,
            4617174756850892801,
            4617174761145860098,
            4617174765440827395,
            4617174769735794692,
            4617174774030761989,
            4617174778325729286,
            4617174748260958215,
            5191102217184051200,
            5193354025587671040,
            5191102294493462528,
            1226245742482522112,
            64,
            4617174774030761993,
            5198420613823102976,
            1,
            5193354051357474816,
            5191102264428691456,
            5189976364521848832,
            0,
            5198983563776655360,
            1,
            5191102294493462528,
            5188850460320104448,
            1226245742482522112,
            13,
            4617174778325729287,
            4612389708017270782,
            5193354038472572928,
            5193354038472572928,
            5193354038472572928,
            5191102268723658752,
            5191102273018626048,
            5191102277313593344,
            5191102281608560640,
            5191102285903527936,
            2345108766317314046,
            146226256843603965,
            8,
            5191102221479018496,
            5191102225773985792,
            5191102230068953088,
            5191102234363920384,
            5191102238658887680,
            2345108766317314046,
            290341444919459839,
            0,
            290341444919459839,
            1,
            145944781866893311,
            12,
            5191102221479018496,
            5191102225773985792,
            5191102230068953088,
            5191102234363920384,
            5191102238658887680,
            5191102242953854976,
            1226245742482522112,
            34,
            74168662805676031,
            10,
            5191102221479018496,
            5191102225773985792,
            5191102230068953088,
            5191102234363920384,
            5191102238658887680,
            5191102242953854976,
            1226245742482522112,
            68,
            5191102242953854976,
            5198983563776458752,
            3618502788666131213697322783095070105623107215331596699973092056135872020480,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020446,
            2345108766317314046,
            5188850460319907840,
            4612389708016353279,
            5191102242953854976,
            5188850468909842432,
            5188850464614875136,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020364,
            4612389712311320575,
            5198983563776327680,
            2,
            5193354047062507520,
            2345108766317314046,
            5198983563776458752,
            2,
            5191102247248822272,
            2345108766317314046,
            290341444919459839,
            4,
            5191102230068953088,
            5191102260133724160,
            5191102264428691456,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020348,
            5191102242953854976,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020469,
            5189976364521848832,
            4,
            4611826758063128575,
            5191102234363920384,
            5188850468909842432,
            5189976364521848832,
            1,
            5188850464614875136,
            5188287514661257216,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020257,
            5188850460319907840,
            4611826758060965887,
            4611826762355933145,
            4622241336494227458,
            2,
            4614922982807011331,
            5191102225773985792,
            5193353883853750272,
            5193354038472572928,
            5191102238658887680,
            5198983563776655360,
            1,
            5191102247248822272,
            5188850460320104448,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020392,
            4623648711380271103,
            5193354038472572928,
            5193354038472572928,
            5193354038472572928,
            5193354038472572928,
            5191102268723658752,
            2345108766317314046,
            290341444919459839,
            2,
            5191102242953854976,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020430,
            4617174774030761984,
            5188287510366617600,
            4612389708016156671,
            5188287514661519360,
            4612389712311123967,
            5188287510366486528,
            4622241336496455681,
            3618502788666131213697322783095070105623107215331596699973092056135872020479,
            5198983563776131072,
            2,
            5191102260133724160,
            5191102264428691456,
            1226245742482522112,
            3618502788666131213697322783095070105623107215331596699973092056135872020303,
            5198983563776131072,
            2,
            5199546513730011136,
            5191102230068953088,
            5191102234363920384,
            5198983563776327680,
            1,
            5200109463683497984,
            2345108766317314046
        ];
    }
}
// ---------- End of auto-generated code. ----------

File 3 of 12 : CairoVerifierContract.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract CairoVerifierContract {
    function verifyProofExternal(
        uint256[] calldata proofParams,
        uint256[] calldata proof,
        uint256[] calldata publicInput
    ) external virtual;

    /*
      Returns information that is related to the layout.

      publicMemoryOffset is the offset of the public memory pages' information in the public input.
      selectedBuiltins is a bit-map of builtins that are present in the layout.
    */
    function getLayoutInfo()
        external
        pure
        virtual
        returns (uint256 publicMemoryOffset, uint256 selectedBuiltins);

    uint256 internal constant OUTPUT_BUILTIN_BIT = 0;
    uint256 internal constant PEDERSEN_BUILTIN_BIT = 1;
    uint256 internal constant RANGE_CHECK_BUILTIN_BIT = 2;
    uint256 internal constant ECDSA_BUILTIN_BIT = 3;
    uint256 internal constant BITWISE_BUILTIN_BIT = 4;
    uint256 internal constant EC_OP_BUILTIN_BIT = 5;
    uint256 internal constant KECCAK_BUILTIN_BIT = 6;
    uint256 internal constant POSEIDON_BUILTIN_BIT = 7;
}

File 4 of 12 : CpuPublicInputOffsetsBase.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "PageInfo.sol";

contract CpuPublicInputOffsetsBase is PageInfo {
    // The following constants are offsets of data expected in the public input.
    uint256 internal constant OFFSET_LOG_N_STEPS = 0;
    uint256 internal constant OFFSET_RC_MIN = 1;
    uint256 internal constant OFFSET_RC_MAX = 2;
    uint256 internal constant OFFSET_LAYOUT_CODE = 3;
    uint256 internal constant OFFSET_PROGRAM_BEGIN_ADDR = 4;
    uint256 internal constant OFFSET_PROGRAM_STOP_PTR = 5;
    uint256 internal constant OFFSET_EXECUTION_BEGIN_ADDR = 6;
    uint256 internal constant OFFSET_EXECUTION_STOP_PTR = 7;
    uint256 internal constant OFFSET_OUTPUT_BEGIN_ADDR = 8;
    uint256 internal constant OFFSET_OUTPUT_STOP_PTR = 9;
    uint256 internal constant OFFSET_PEDERSEN_BEGIN_ADDR = 10;
    uint256 internal constant OFFSET_PEDERSEN_STOP_PTR = 11;
    uint256 internal constant OFFSET_RANGE_CHECK_BEGIN_ADDR = 12;
    uint256 internal constant OFFSET_RANGE_CHECK_STOP_PTR = 13;

    // The program segment starts from 1, so that memory address 0 is kept for the null pointer.
    uint256 internal constant INITIAL_PC = 1;
    // The first Cairo instructions are:
    //   ap += n_args; call main; jmp rel 0.
    // As the first two instructions occupy 2 cells each, the "jmp rel 0" instruction is at
    // offset 4 relative to INITIAL_PC.
    uint256 internal constant FINAL_PC = INITIAL_PC + 4;
}

File 5 of 12 : FactRegistry.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "IQueryableFactRegistry.sol";

contract FactRegistry is IQueryableFactRegistry {
    // Mapping: fact hash -> true.
    mapping(bytes32 => bool) private verifiedFact;

    // Indicates whether the Fact Registry has at least one fact registered.
    bool anyFactRegistered = false;

    /*
      Checks if a fact has been verified.
    */
    function isValid(bytes32 fact) external view override returns (bool) {
        return _factCheck(fact);
    }

    /*
      This is an internal method to check if the fact is already registered.
      In current implementation of FactRegistry it's identical to isValid().
      But the check is against the local fact registry,
      So for a derived referral fact registry, it's not the same.
    */
    function _factCheck(bytes32 fact) internal view returns (bool) {
        return verifiedFact[fact];
    }

    function registerFact(bytes32 factHash) internal {
        // This function stores the fact hash in the mapping.
        verifiedFact[factHash] = true;

        // Mark first time off.
        if (!anyFactRegistered) {
            anyFactRegistered = true;
        }
    }

    /*
      Indicates whether at least one fact was registered.
    */
    function hasRegisteredFact() external view override returns (bool) {
        return anyFactRegistered;
    }
}

File 6 of 12 : GpsOutputParser.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "FactRegistry.sol";
import "CpuPublicInputOffsetsBase.sol";

/*
  A utility contract to parse the GPS output.
  See registerGpsFacts for more details.
*/
contract GpsOutputParser is CpuPublicInputOffsetsBase, FactRegistry {
    uint256 internal constant METADATA_TASKS_OFFSET = 1;
    uint256 internal constant METADATA_OFFSET_TASK_OUTPUT_SIZE = 0;
    uint256 internal constant METADATA_OFFSET_TASK_PROGRAM_HASH = 1;
    uint256 internal constant METADATA_OFFSET_TASK_N_TREE_PAIRS = 2;
    uint256 internal constant METADATA_TASK_HEADER_SIZE = 3;

    uint256 internal constant METADATA_OFFSET_TREE_PAIR_N_PAGES = 0;
    uint256 internal constant METADATA_OFFSET_TREE_PAIR_N_NODES = 1;

    uint256 internal constant NODE_STACK_OFFSET_HASH = 0;
    uint256 internal constant NODE_STACK_OFFSET_END = 1;
    // The size of each node in the node stack.
    uint256 internal constant NODE_STACK_ITEM_SIZE = 2;

    uint256 internal constant FIRST_CONTINUOUS_PAGE_INDEX = 1;

    /*
      Logs the program output fact together with the relevant continuous memory pages' hashes.
      The event is emitted for each registered fact.
    */
    event LogMemoryPagesHashes(bytes32 programOutputFact, bytes32[] pagesHashes);

    /*
      Parses the GPS program output (using taskMetadata, which should be verified by the caller),
      and registers the facts of the tasks which were executed.

      The first entry in taskMetadata is the number of tasks.

      For each task, the structure is as follows:
        1. Size (including the size and hash fields).
        2. Program hash.
        3. The number of pairs in the Merkle tree structure (see below).
        4. The Merkle tree structure (see below).

      The fact of each task is stored as a (non-binary) Merkle tree.
      Leaf nodes are labeled with the hash of their data.
      Each non-leaf node is labeled as 1 + the hash of (node0, end0, node1, end1, ...)
      where node* is a label of a child children and end* is the total number of data words up to
      and including that node and its children (including the previous sibling nodes).
      We add 1 to the result of the hash to prevent an attacker from using a preimage of a leaf node
      as a preimage of a non-leaf hash and vice versa.

      The structure of the tree is passed as a list of pairs (n_pages, n_nodes), and the tree is
      constructed using a stack of nodes (initialized to an empty stack) by repeating for each pair:
      1. Add n_pages to the stack of nodes.
      2. Pop the top n_nodes, construct a parent node for them, and push it back to the stack.
      After applying the steps above, the stack much contain exactly one node, which will
      constitute the root of the Merkle tree.
      For example, [(2, 2)] will create a Merkle tree with a root and two direct children, while
      [(3, 2), (0, 2)] will create a Merkle tree with a root whose left child is a leaf and
      right child has two leaf children.

      Assumptions: taskMetadata and cairoAuxInput are verified externally.
    */
    function registerGpsFacts(
        uint256[] calldata taskMetadata,
        uint256[] memory publicMemoryPages,
        uint256 outputStartAddress
    ) internal {
        uint256 totalNumPages = publicMemoryPages[0];

        // Allocate some of the loop variables here to avoid the stack-too-deep error.
        uint256 task;
        uint256 nTreePairs;
        uint256 nTasks = taskMetadata[0];

        // Contains fact hash with the relevant memory pages' hashes.
        // Size is bounded from above with the total number of pages. Three extra places are
        // dedicated for the fact hash and the array address and length.
        uint256[] memory pageHashesLogData = new uint256[](totalNumPages + 3);
        // Relative address to the beginning of the memory pages' hashes in the array.
        pageHashesLogData[1] = 0x40;

        uint256 taskMetadataOffset = METADATA_TASKS_OFFSET;

        // Skip the 5 first output cells which contain the bootloader config, the number of tasks
        // and the size and program hash of the first task. curAddr points to the output of the
        // first task.
        uint256 curAddr = outputStartAddress + 5;

        // Skip the main page.
        uint256 curPage = FIRST_CONTINUOUS_PAGE_INDEX;

        // Bound the size of the stack by the total number of pages.
        // TODO(lior, 15/04/2022): Get a better bound on the size of the stack.
        uint256[] memory nodeStack = new uint256[](NODE_STACK_ITEM_SIZE * totalNumPages);

        // Copy to memory to workaround the "stack too deep" error.
        uint256[] memory taskMetadataCopy = taskMetadata;

        uint256[PAGE_INFO_SIZE] memory pageInfoPtr;
        assembly {
            // Skip the array length and the first page.
            pageInfoPtr := add(add(publicMemoryPages, 0x20), PAGE_INFO_SIZE_IN_BYTES)
        }

        // Register the fact for each task.
        for (task = 0; task < nTasks; task++) {
            uint256 curOffset = 0;
            uint256 firstPageOfTask = curPage;
            nTreePairs = taskMetadataCopy[taskMetadataOffset + METADATA_OFFSET_TASK_N_TREE_PAIRS];

            // Build the Merkle tree using a stack (see the function documentation) to compute
            // the fact.
            uint256 nodeStackLen = 0;
            for (uint256 treePair = 0; treePair < nTreePairs; treePair++) {
                // Add nPages to the stack of nodes.
                uint256 nPages = taskMetadataCopy[
                    taskMetadataOffset +
                        METADATA_TASK_HEADER_SIZE +
                        2 *
                        treePair +
                        METADATA_OFFSET_TREE_PAIR_N_PAGES
                ];

                // Ensure 'nPages' is bounded from above as a sanity check
                // (the bound is somewhat arbitrary).
                require(nPages < 2**20, "Invalid value of n_pages in tree structure.");

                for (uint256 i = 0; i < nPages; i++) {
                    (uint256 pageSize, uint256 pageHash) = pushPageToStack(
                        pageInfoPtr,
                        curAddr,
                        curOffset,
                        nodeStack,
                        nodeStackLen
                    );
                    pageHashesLogData[curPage - firstPageOfTask + 3] = pageHash;
                    curPage += 1;
                    nodeStackLen += 1;
                    curAddr += pageSize;
                    curOffset += pageSize;

                    assembly {
                        pageInfoPtr := add(pageInfoPtr, PAGE_INFO_SIZE_IN_BYTES)
                    }
                }

                // Pop the top n_nodes, construct a parent node for them, and push it back to the
                // stack.
                uint256 nNodes = taskMetadataCopy[
                    taskMetadataOffset +
                        METADATA_TASK_HEADER_SIZE +
                        2 *
                        treePair +
                        METADATA_OFFSET_TREE_PAIR_N_NODES
                ];
                if (nNodes != 0) {
                    nodeStackLen = constructNode(nodeStack, nodeStackLen, nNodes);
                }
            }
            require(nodeStackLen == 1, "Node stack must contain exactly one item.");

            uint256 programHash = taskMetadataCopy[
                taskMetadataOffset + METADATA_OFFSET_TASK_PROGRAM_HASH
            ];

            // Verify that the sizes of the pages correspond to the task output, to make
            // sure that the computed hash is indeed the hash of the entire output of the task.
            {
                uint256 outputSize = taskMetadataCopy[
                    taskMetadataOffset + METADATA_OFFSET_TASK_OUTPUT_SIZE
                ];

                require(
                    nodeStack[NODE_STACK_OFFSET_END] + 2 == outputSize,
                    "The sum of the page sizes does not match output size."
                );
            }

            uint256 programOutputFact = nodeStack[NODE_STACK_OFFSET_HASH];
            bytes32 fact = keccak256(abi.encode(programHash, programOutputFact));

            // Update taskMetadataOffset.
            taskMetadataOffset += METADATA_TASK_HEADER_SIZE + 2 * nTreePairs;

            {
                // Log the output Merkle root with the hashes of the relevant memory pages.
                // Instead of emit, we use log1 https://docs.soliditylang.org/en/v0.4.24/assembly.html,
                // https://docs.soliditylang.org/en/v0.6.2/abi-spec.html#use-of-dynamic-types.

                bytes32 logHash = keccak256("LogMemoryPagesHashes(bytes32,bytes32[])");
                assembly {
                    let buf := add(pageHashesLogData, 0x20)
                    // Number of memory pages that are relevant for this fact.
                    let length := sub(curPage, firstPageOfTask)
                    mstore(buf, programOutputFact)
                    mstore(add(buf, 0x40), length)
                    log1(buf, mul(add(length, 3), 0x20), logHash)
                }
            }
            registerFact(fact);

            // Move curAddr to the output of the next task (skipping the size and hash fields).
            curAddr += 2;
        }

        require(totalNumPages == curPage, "Not all memory pages were processed.");
    }

    /*
      Push one page (curPage) to the top of the node stack.
      curAddr is the memory address, curOffset is the offset from the beginning of the task output.
      Verifies that the page has the right start address and returns the page size and the page
      hash.
    */
    function pushPageToStack(
        uint256[PAGE_INFO_SIZE] memory pageInfoPtr,
        uint256 curAddr,
        uint256 curOffset,
        uint256[] memory nodeStack,
        uint256 nodeStackLen
    ) private pure returns (uint256 pageSize, uint256 pageHash) {
        // Read the first address, page size and hash.
        uint256 pageAddr = pageInfoPtr[PAGE_INFO_ADDRESS_OFFSET];
        pageSize = pageInfoPtr[PAGE_INFO_SIZE_OFFSET];
        pageHash = pageInfoPtr[PAGE_INFO_HASH_OFFSET];

        // Ensure 'pageSize' is bounded as a sanity check (the bound is somewhat arbitrary).
        require(pageSize < 2**30, "Invalid page size.");
        require(pageAddr == curAddr, "Invalid page address.");

        nodeStack[NODE_STACK_ITEM_SIZE * nodeStackLen + NODE_STACK_OFFSET_END] =
            curOffset +
            pageSize;
        nodeStack[NODE_STACK_ITEM_SIZE * nodeStackLen + NODE_STACK_OFFSET_HASH] = pageHash;
    }

    /*
      Pops the top nNodes nodes from the stack and pushes one parent node instead.
      Returns the new value of nodeStackLen.
    */
    function constructNode(
        uint256[] memory nodeStack,
        uint256 nodeStackLen,
        uint256 nNodes
    ) private pure returns (uint256) {
        require(nNodes <= nodeStackLen, "Invalid value of n_nodes in tree structure.");
        // The end of the node is the end of the last child.
        uint256 newNodeEnd = nodeStack[
            NODE_STACK_ITEM_SIZE * (nodeStackLen - 1) + NODE_STACK_OFFSET_END
        ];
        uint256 newStackLen = nodeStackLen - nNodes;
        // Compute node hash.
        uint256 nodeStart = 0x20 + newStackLen * NODE_STACK_ITEM_SIZE * 0x20;
        uint256 newNodeHash;
        assembly {
            newNodeHash := keccak256(
                add(nodeStack, nodeStart),
                mul(
                    nNodes,
                    // NODE_STACK_ITEM_SIZE * 0x20 =
                    0x40
                )
            )
        }

        nodeStack[NODE_STACK_ITEM_SIZE * newStackLen + NODE_STACK_OFFSET_END] = newNodeEnd;
        // Add one to the new node hash to distinguish it from the hash of a leaf (a page).
        nodeStack[NODE_STACK_ITEM_SIZE * newStackLen + NODE_STACK_OFFSET_HASH] = newNodeHash + 1;
        return newStackLen + 1;
    }
}

File 7 of 12 : IFactRegistry.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

/*
  The Fact Registry design pattern is a way to separate cryptographic verification from the
  business logic of the contract flow.

  A fact registry holds a hash table of verified "facts" which are represented by a hash of claims
  that the registry hash check and found valid. This table may be queried by accessing the
  isValid() function of the registry with a given hash.

  In addition, each fact registry exposes a registry specific function for submitting new claims
  together with their proofs. The information submitted varies from one registry to the other
  depending of the type of fact requiring verification.

  For further reading on the Fact Registry design pattern see this
  `StarkWare blog post <https://medium.com/starkware/the-fact-registry-a64aafb598b6>`_.
*/
interface IFactRegistry {
    /*
      Returns true if the given fact was previously registered in the contract.
    */
    function isValid(bytes32 fact) external view returns (bool);
}

File 8 of 12 : IQueryableFactRegistry.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "IFactRegistry.sol";

/*
  Extends the IFactRegistry interface with a query method that indicates
  whether the fact registry has successfully registered any fact or is still empty of such facts.
*/
interface IQueryableFactRegistry is IFactRegistry {
    /*
      Returns true if at least one fact has been registered.
    */
    function hasRegisteredFact() external view returns (bool);
}

File 9 of 12 : Identity.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

interface Identity {
    /*
      Allows a caller to ensure that the provided address is of the expected type and version.
    */
    function identify() external pure returns (string memory);
}

File 10 of 12 : MemoryPageFactRegistry.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "FactRegistry.sol";

contract MemoryPageFactRegistryConstants {
    // A page based on a list of pairs (address, value).
    // In this case, memoryHash = hash(address, value, address, value, address, value, ...).
    uint256 internal constant REGULAR_PAGE = 0;
    // A page based on adjacent memory cells, starting from a given address.
    // In this case, memoryHash = hash(value, value, value, ...).
    uint256 internal constant CONTINUOUS_PAGE = 1;
}

/*
  A fact registry for the claim:
    I know n pairs (addr, value) for which the hash of the pairs is memoryHash, and the cumulative
    product: \prod_i( z - (addr_i + alpha * value_i) ) is prod.
  The exact format of the hash depends on the type of the page
  (see MemoryPageFactRegistryConstants).
  The fact consists of (pageType, prime, n, z, alpha, prod, memoryHash, address).
  Note that address is only available for CONTINUOUS_PAGE, and otherwise it is 0.
*/
contract MemoryPageFactRegistry is FactRegistry, MemoryPageFactRegistryConstants {
    event LogMemoryPageFactRegular(bytes32 factHash, uint256 memoryHash, uint256 prod);
    event LogMemoryPageFactContinuous(bytes32 factHash, uint256 memoryHash, uint256 prod);

    /*
      Registers a fact based of the given memory (address, value) pairs (REGULAR_PAGE).
    */
    function registerRegularMemoryPage(
        uint256[] calldata memoryPairs,
        uint256 z,
        uint256 alpha,
        uint256 prime
    )
        external
        returns (
            bytes32 factHash,
            uint256 memoryHash,
            uint256 prod
        )
    {
        // Ensure 'memoryPairs.length' is bounded as a sanity check (the bound is somewhat arbitrary).
        require(memoryPairs.length < 2**20, "Too many memory values.");
        require(memoryPairs.length % 2 == 0, "Size of memoryPairs must be even.");
        require(z < prime, "Invalid value of z.");
        require(alpha < prime, "Invalid value of alpha.");
        (factHash, memoryHash, prod) = computeFactHash(memoryPairs, z, alpha, prime);
        emit LogMemoryPageFactRegular(factHash, memoryHash, prod);

        registerFact(factHash);
    }

    function computeFactHash(
        uint256[] memory memoryPairs,
        uint256 z,
        uint256 alpha,
        uint256 prime
    )
        private
        pure
        returns (
            bytes32 factHash,
            uint256 memoryHash,
            uint256 prod
        )
    {
        uint256 memorySize = memoryPairs.length / 2; // NOLINT: divide-before-multiply.

        prod = 1;

        assembly {
            let memoryPtr := add(memoryPairs, 0x20)

            // Each value of memoryPairs is a pair: (address, value).
            let lastPtr := add(memoryPtr, mul(memorySize, 0x40))
            for {
                let ptr := memoryPtr
            } lt(ptr, lastPtr) {
                ptr := add(ptr, 0x40)
            } {
                // Compute address + alpha * value.
                let address_value_lin_comb := addmod(
                    // address=
                    mload(ptr),
                    mulmod(
                        // value=
                        mload(add(ptr, 0x20)),
                        alpha,
                        prime
                    ),
                    prime
                )
                prod := mulmod(prod, add(z, sub(prime, address_value_lin_comb)), prime)
            }

            memoryHash := keccak256(
                memoryPtr,
                mul(
                    // 0x20 * 2.
                    0x40,
                    memorySize
                )
            )
        }

        factHash = keccak256(
            abi.encodePacked(
                REGULAR_PAGE,
                prime,
                memorySize,
                z,
                alpha,
                prod,
                memoryHash,
                uint256(0)
            )
        );
    }

    /*
      Registers a fact based on the given values, assuming continuous addresses.
      values should be [value at startAddr, value at (startAddr + 1), ...].
    */
    function registerContinuousMemoryPage(
        // NOLINT: external-function.
        uint256 startAddr,
        uint256[] memory values,
        uint256 z,
        uint256 alpha,
        uint256 prime
    )
        public
        returns (
            bytes32 factHash,
            uint256 memoryHash,
            uint256 prod
        )
    {
        require(values.length < 2**20, "Too many memory values.");
        require(prime < 2**254, "prime is too big for the optimizations in this function.");
        require(z < prime, "Invalid value of z.");
        require(alpha < prime, "Invalid value of alpha.");
        // Ensure 'startAddr' less then prime and bounded as a sanity check (the bound is somewhat arbitrary).
        require((startAddr < prime) && (startAddr < 2**64), "Invalid value of startAddr.");

        uint256 nValues = values.length;

        assembly {
            // Initialize prod to 1.
            prod := 1
            // Initialize valuesPtr to point to the first value in the array.
            let valuesPtr := add(values, 0x20)

            let minus_z := mod(sub(prime, z), prime)

            // Start by processing full batches of 8 cells, addr represents the last address in each
            // batch.
            let addr := add(startAddr, 7)
            let lastAddr := add(startAddr, nValues)
            for {

            } lt(addr, lastAddr) {
                addr := add(addr, 8)
            } {
                // Compute the product of (lin_comb - z) instead of (z - lin_comb), since we're
                // doing an even number of iterations, the result is the same.
                prod := mulmod(
                    prod,
                    mulmod(
                        add(add(sub(addr, 7), mulmod(mload(valuesPtr), alpha, prime)), minus_z),
                        add(
                            add(sub(addr, 6), mulmod(mload(add(valuesPtr, 0x20)), alpha, prime)),
                            minus_z
                        ),
                        prime
                    ),
                    prime
                )

                prod := mulmod(
                    prod,
                    mulmod(
                        add(
                            add(sub(addr, 5), mulmod(mload(add(valuesPtr, 0x40)), alpha, prime)),
                            minus_z
                        ),
                        add(
                            add(sub(addr, 4), mulmod(mload(add(valuesPtr, 0x60)), alpha, prime)),
                            minus_z
                        ),
                        prime
                    ),
                    prime
                )

                prod := mulmod(
                    prod,
                    mulmod(
                        add(
                            add(sub(addr, 3), mulmod(mload(add(valuesPtr, 0x80)), alpha, prime)),
                            minus_z
                        ),
                        add(
                            add(sub(addr, 2), mulmod(mload(add(valuesPtr, 0xa0)), alpha, prime)),
                            minus_z
                        ),
                        prime
                    ),
                    prime
                )

                prod := mulmod(
                    prod,
                    mulmod(
                        add(
                            add(sub(addr, 1), mulmod(mload(add(valuesPtr, 0xc0)), alpha, prime)),
                            minus_z
                        ),
                        add(add(addr, mulmod(mload(add(valuesPtr, 0xe0)), alpha, prime)), minus_z),
                        prime
                    ),
                    prime
                )

                valuesPtr := add(valuesPtr, 0x100)
            }

            // Handle leftover.
            // Translate addr to the beginning of the last incomplete batch.
            addr := sub(addr, 7)
            for {

            } lt(addr, lastAddr) {
                addr := add(addr, 1)
            } {
                let address_value_lin_comb := addmod(
                    addr,
                    mulmod(mload(valuesPtr), alpha, prime),
                    prime
                )
                prod := mulmod(prod, add(z, sub(prime, address_value_lin_comb)), prime)
                valuesPtr := add(valuesPtr, 0x20)
            }

            memoryHash := keccak256(add(values, 0x20), mul(0x20, nValues))
        }

        factHash = keccak256(
            abi.encodePacked(CONTINUOUS_PAGE, prime, nValues, z, alpha, prod, memoryHash, startAddr)
        );

        emit LogMemoryPageFactContinuous(factHash, memoryHash, prod);

        registerFact(factHash);
    }
}

File 11 of 12 : PageInfo.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

contract PageInfo {
    uint256 public constant PAGE_INFO_SIZE = 3;
    // PAGE_INFO_SIZE_IN_BYTES cannot reference PAGE_INFO_SIZE as only direct constants are
    // supported in assembly.
    uint256 public constant PAGE_INFO_SIZE_IN_BYTES = 3 * 32;

    uint256 public constant PAGE_INFO_ADDRESS_OFFSET = 0;
    uint256 public constant PAGE_INFO_SIZE_OFFSET = 1;
    uint256 public constant PAGE_INFO_HASH_OFFSET = 2;

    // A regular page entry is a (address, value) pair stored as 2 uint256 words.
    uint256 internal constant MEMORY_PAIR_SIZE = 2;
}

File 12 of 12 : PrimeFieldElement0.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

contract PrimeFieldElement0 {
    uint256 internal constant K_MODULUS =
        0x800000000000011000000000000000000000000000000000000000000000001;
    uint256 internal constant K_MONTGOMERY_R =
        0x7fffffffffffdf0ffffffffffffffffffffffffffffffffffffffffffffffe1;
    uint256 internal constant K_MONTGOMERY_R_INV =
        0x40000000000001100000000000012100000000000000000000000000000000;
    uint256 internal constant GENERATOR_VAL = 3;
    uint256 internal constant ONE_VAL = 1;

    function fromMontgomery(uint256 val) internal pure returns (uint256 res) {
        // uint256 res = fmul(val, kMontgomeryRInv);
        assembly {
            res := mulmod(val, K_MONTGOMERY_R_INV, K_MODULUS)
        }
        return res;
    }

    function fromMontgomeryBytes(bytes32 bs) internal pure returns (uint256) {
        // Assuming bs is a 256bit bytes object, in Montgomery form, it is read into a field
        // element.
        uint256 res = uint256(bs);
        return fromMontgomery(res);
    }

    function toMontgomeryInt(uint256 val) internal pure returns (uint256 res) {
        //uint256 res = fmul(val, kMontgomeryR);
        assembly {
            res := mulmod(val, K_MONTGOMERY_R, K_MODULUS)
        }
        return res;
    }

    function fmul(uint256 a, uint256 b) internal pure returns (uint256 res) {
        //uint256 res = mulmod(a, b, kModulus);
        assembly {
            res := mulmod(a, b, K_MODULUS)
        }
        return res;
    }

    function fadd(uint256 a, uint256 b) internal pure returns (uint256 res) {
        // uint256 res = addmod(a, b, kModulus);
        assembly {
            res := addmod(a, b, K_MODULUS)
        }
        return res;
    }

    function fsub(uint256 a, uint256 b) internal pure returns (uint256 res) {
        // uint256 res = addmod(a, kModulus - b, kModulus);
        assembly {
            res := addmod(a, sub(K_MODULUS, b), K_MODULUS)
        }
        return res;
    }

    function fpow(uint256 val, uint256 exp) internal view returns (uint256) {
        return expmod(val, exp, K_MODULUS);
    }

    function expmod(
        uint256 base,
        uint256 exponent,
        uint256 modulus
    ) private view returns (uint256 res) {
        assembly {
            let p := mload(0x40)
            mstore(p, 0x20) // Length of Base.
            mstore(add(p, 0x20), 0x20) // Length of Exponent.
            mstore(add(p, 0x40), 0x20) // Length of Modulus.
            mstore(add(p, 0x60), base) // Base.
            mstore(add(p, 0x80), exponent) // Exponent.
            mstore(add(p, 0xa0), modulus) // Modulus.
            // Call modexp precompile.
            if iszero(staticcall(gas(), 0x05, p, 0xc0, p, 0x20)) {
                revert(0, 0)
            }
            res := mload(p)
        }
    }

    function inverse(uint256 val) internal view returns (uint256) {
        return expmod(val, K_MODULUS - 2, K_MODULUS);
    }
}

Settings
{
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {},
  "remappings": [],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "evmVersion": "istanbul",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"bootloaderProgramContract","type":"address"},{"internalType":"address","name":"memoryPageFactRegistry_","type":"address"},{"internalType":"address[]","name":"cairoVerifierContracts","type":"address[]"},{"internalType":"uint256","name":"hashedSupportedCairoVerifiers","type":"uint256"},{"internalType":"uint256","name":"simpleBootloaderProgramHash","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"programOutputFact","type":"bytes32"},{"indexed":false,"internalType":"bytes32[]","name":"pagesHashes","type":"bytes32[]"}],"name":"LogMemoryPagesHashes","type":"event"},{"inputs":[],"name":"PAGE_INFO_ADDRESS_OFFSET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAGE_INFO_HASH_OFFSET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAGE_INFO_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAGE_INFO_SIZE_IN_BYTES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAGE_INFO_SIZE_OFFSET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBootloaderConfig","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasRegisteredFact","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"identify","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"fact","type":"bytes32"}],"name":"isValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"proofParams","type":"uint256[]"},{"internalType":"uint256[]","name":"proof","type":"uint256[]"},{"internalType":"uint256[]","name":"taskMetadata","type":"uint256[]"},{"internalType":"uint256[]","name":"cairoAuxInput","type":"uint256[]"},{"internalType":"uint256","name":"cairoVerifierId","type":"uint256"}],"name":"verifyProofAndRegister","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040526001805460ff191690553480156200001b57600080fd5b506040516200209638038062002096833981810160405260a08110156200004157600080fd5b815160208301516040808501805191519395929483019291846401000000008211156200006d57600080fd5b9083019060208201858111156200008357600080fd5b8251866020820283011164010000000082111715620000a157600080fd5b82525081516020918201928201910280838360005b83811015620000d0578181015183820152602001620000b6565b50505050919091016040908152602083015192015160018054610100600160a81b0319166101006001600160a01b038b81169190910291909117909155600280546001600160a01b03191691891691909117905585519294509250506001600160401b03811180156200014257600080fd5b506040519080825280602002602001820160405280156200016d578160200160208202803683370190505b5080516200018491600391602090910190620001fb565b5060005b8351811015620001e7578381815181106200019f57fe5b602002602001015160038281548110620001b557fe5b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905560010162000188565b5060809190915260a0525062000286915050565b82805482825590600052602060002090810192821562000253579160200282015b828111156200025357825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906200021c565b506200026192915062000265565b5090565b5b80821115620002615780546001600160a01b031916815560010162000266565b60805160a051611de2620002b4600039806103435280610e825250806103645280610edd5250611de26000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80639b3b76cc11610076578063d6354e151161005b578063d6354e15146102af578063e5b62b29146102b7578063eeb72866146102bf576100be565b80639b3b76cc1461013f578063b7a771f7146102a7576100be565b80634c14a6f9116100a75780634c14a6f9146100fe5780635b4c41c2146101065780636a9385671461010e576100be565b806329e10520146100c35780632f4da80e146100dd575b600080fd5b6100cb61033c565b60408051918252519081900360200190f35b6100e5610341565b6040805192835260208301919091528051918290030190f35b6100cb610387565b6100cb61038c565b61012b6004803603602081101561012457600080fd5b5035610391565b604080519115158252519081900360200190f35b6102a5600480360360a081101561015557600080fd5b81019060208101813564010000000081111561017057600080fd5b82018360208201111561018257600080fd5b803590602001918460208302840111640100000000831117156101a457600080fd5b9193909290916020810190356401000000008111156101c257600080fd5b8201836020820111156101d457600080fd5b803590602001918460208302840111640100000000831117156101f657600080fd5b91939092909160208101903564010000000081111561021457600080fd5b82018360208201111561022657600080fd5b8035906020019184602083028401116401000000008311171561024857600080fd5b91939092909160208101903564010000000081111561026657600080fd5b82018360208201111561027857600080fd5b8035906020019184602083028401116401000000008311171561029a57600080fd5b9193509150356103a2565b005b6100cb610981565b61012b610986565b6100cb61098f565b6102c7610994565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103015781810151838201526020016102e9565b50505050905090810190601f16801561032e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600281565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000009091565b600381565b600181565b600061039c826109b4565b92915050565b600354811061041257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f636169726f56657269666965724964206973206f7574206f662072616e67652e604482015290519081900360640190fd5b60006003828154811061042157fe5b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff16915036906104747ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8601828789611b91565b9150915060606000808573ffffffffffffffffffffffffffffffffffffffff16638080fdfb6040518163ffffffff1660e01b8152600401604080518083038186803b1580156104c257600080fd5b505afa1580156104d6573d6000803e3d6000fd5b505050506040513d60408110156104ec57600080fd5b508051602090910151909250905081881161056857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420636169726f417578496e707574206c656e6774682e000000604482015290519081900360640190fd5b61057484838188611b91565b808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250845194975093879350849250151590506105b757fe5b60200260200101519050612710811061063157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c6964206e50616765732e0000000000000000000000000000000000604482015290519081900360640190fd5b8351600482021461068d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611c0b6021913960400191505060405180910390fd5b600080600061069f8f8f8f8f896109c9565b92509250925082876001815181106106b357fe5b60200260200101511461072757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c69642073697a6520666f72206d656d6f7279207061676520302e00604482015290519081900360640190fd5b818760028151811061073557fe5b6020026020010151146107a957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c6964206861736820666f72206d656d6f7279207061676520302e00604482015290519081900360640190fd5b808760038602815181106107b957fe5b602002602001015114610817576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180611ca4602d913960400191505060405180910390fd5b5050505050508373ffffffffffffffffffffffffffffffffffffffff16631cb7dd798e8e8e8e88886040518763ffffffff1660e01b81526004018080602001806020018060200184810384528a8a82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018581038452888152602090810191508990890280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018581038352868152602090810191508790870280828437600081840152601f19601f8201169050808301925050509950505050505050505050600060405180830381600087803b15801561093b57600080fd5b505af115801561094f573d6000803e3d6000fd5b505050506109728989838a8a600881811061096657fe5b9050602002013561141a565b50505050505050505050505050565b606081565b60015460ff1690565b600081565b6060604051806060016040528060258152602001611be660259139905090565b60009081526020819052604090205460ff1690565b600080600080888860008181106109dc57fe5b90506020020135905063400000008110610a5757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c6964206e756d626572206f66207461736b732e0000000000000000604482015290519081900360640190fd5b6002818102610247019450606090850267ffffffffffffffff81118015610a7d57600080fd5b50604051908082528060200260200182016040528015610aa7578160200160208202803683370190505b5090506000610ab4611b53565b60018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634b6cee596040518163ffffffff1660e01b81526004016146406040518083038186803b158015610b1b57600080fd5b505afa158015610b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614640811015610b5557600080fd5b50905060005b610232811015610bbc5760018101848481518110610b7557fe5b60200260200101818152505081816102328110610b8e57fe5b6020020151848460010181518110610ba257fe5b602090810291909101015260029290920191600101610b5b565b5050600089896006818110610bcd57fe5b9050602002013590506002811015610c4657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f496e76616c696420657865637574696f6e20626567696e20616464726573732e604482015290519081900360640190fd5b60028103838360000181518110610c5957fe5b60200260200101818152505080838360010181518110610c7557fe5b60200260200101818152505060018103838360020181518110610c9457fe5b6020026020010181815250506000838360030181518110610cb157fe5b602002602001018181525050600482019150600060088b8b6007818110610cd457fe5b9050602002013503905060006008905060005b6008811015610dee57808401868681518110610cff57fe5b60209081029190910101528551601086019084830190889083908110610d2157fe5b602090810291909101015260018c1615610d9f578d8d84818110610d4157fe5b90506020020135878760010181518110610d5757fe5b6020026020010181815250508d8d84600101818110610d7257fe5b90506020020135878260010181518110610d8857fe5b602002602001018181525050600283019250610dda565b6000878760010181518110610db057fe5b6020026020010181815250506000878260010181518110610dcd57fe5b6020026020010181815250505b5060019a8b1c9a6002959095019401610ce7565b508915610e46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611c806024913960400191505060405180910390fd5b505050601001600089896008818110610e5b57fe5b90506020020135905080838360000181518110610e7457fe5b6020026020010181815250507f0000000000000000000000000000000000000000000000000000000000000000838360010181518110610eb057fe5b60200260200101818152505080600101838360020181518110610ecf57fe5b6020026020010181815250507f0000000000000000000000000000000000000000000000000000000000000000838360030181518110610f0b57fe5b60200260200101818152505080600201838360040181518110610f2a57fe5b60200260200101818152505083838360050181518110610f4657fe5b6020026020010181815250506006820191506003810190503660008d8d6001908092610f7493929190611b91565b9150915060005b8681101561115557600083836000818110610f9257fe5b90506020020135905080600211158015610faf5750634000000081105b61101a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c6964207461736b206f75747075742073697a652e00000000000000604482015290519081900360640190fd5b60008484600181811061102957fe5b90506020020135905060008585600281811061104157fe5b9050602002013590508060011115801561105d57506210000081105b6110b2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180611d786035913960400191505060405180910390fd5b868989600001815181106110c257fe5b602002602001018181525050828989600101815181106110de57fe5b602002602001018181525050866001018989600201815181106110fd57fe5b6020026020010181815250508189896003018151811061111957fe5b6020908102919091010152600497909701969582019561114185600360028402018189611b91565b955095505050508080600101915050610f7b565b5080156111c357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c6964206c656e677468206f66207461736b4d657461646174612e00604482015290519081900360640190fd5b828c8c60098181106111d157fe5b905060200201351461122e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611cd16023913960400191505060405180910390fd5b5050508082511461128a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180611bbd6029913960400191505060405180910390fd5b600089897ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81018181106112ba57fe5b90506020020135905060008a8a60018d8d9050038181106112d757fe5b9050602002013590506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663405a63628685857f08000000000000110000000000000000000000000000000000000000000000016040518563ffffffff1660e01b81526004018080602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b838110156113a557818101518382015260200161138d565b5050505090500195505050505050606060405180830381600087803b1580156113cd57600080fd5b505af11580156113e1573d6000803e3d6000fd5b505050506040513d60608110156113f757600080fd5b506020810151604090910151999f909e50989c50979a5050505050505050505050565b60008260008151811061142957fe5b6020026020010151905060008060008787600081811061144557fe5b90506020020135905060608460030167ffffffffffffffff8111801561146a57600080fd5b50604051908082528060200260200182016040528015611494578160200160208202803683370190505b5090506040816001815181106114a657fe5b60209081029190910101526001600587018160606002890267ffffffffffffffff811180156114d457600080fd5b506040519080825280602002602001820160405280156114fe578160200160208202803683370190505b50905060608d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509293506115439250611b73915050565b506000985060808c015b878a10156118575760008085905083600289018151811061156a57fe5b60200260200101519a506000805b8c81101561169d5760008660008360020260038e0101018151811061159957fe5b602002602001015190506210000081106115fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180611d18602b913960400191505060405180910390fd5b60005b8181101561165957600080611619898e8a8e8a6118c0565b91509150808f888e036003018151811061162f57fe5b6020908102919091010152509a8b019a60019a8b019a606098909801979601959384019301611601565b5060008760018460020260038f0101018151811061167357fe5b6020026020010151905080600014611693576116908985836119f9565b93505b5050600101611578565b50806001146116f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180611c2c6029913960400191505060405180910390fd5b60008560018b018151811061170857fe5b6020026020010151905060008660008c018151811061172357fe5b60200260200101519050808860018151811061173b57fe5b60200260200101516002011461179c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180611d436035913960400191505060405180910390fd5b506000876000815181106117ac57fe5b602002602001015190506000828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090508e6002026003018c019b5060007f73b132cb33951232d83dc0f1f81c2d10f9a2598f057404ed02756716092097bb905060208e01868c03848252806040830152826020600383010283a150505061183f81611ae3565b50506001909d019c505050600295909501945061154d565b838b146118af576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611cf46024913960400191505060405180910390fd5b505050505050505050505050505050565b84516020860151604087015190916340000000831061194057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c696420706167652073697a652e0000000000000000000000000000604482015290519081900360640190fd5b8681146119ae57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c6964207061676520616464726573732e0000000000000000000000604482015290519081900360640190fd5b8286018560018660020201815181106119c357fe5b602002602001018181525050818560008660020201815181106119e257fe5b602002602001018181525050509550959350505050565b600082821115611a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180611c55602b913960400191505060405180910390fd5b60008460018086036002020181518110611a6a57fe5b6020026020010151905060008385039050600060028202602002602001905060006040860282890120905083886001856002020181518110611aa857fe5b60200260200101818152505080600101886000856002020181518110611aca57fe5b6020908102919091010152505060010195945050505050565b600081815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091555460ff16611b5057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016811790555b50565b604051806146400160405280610232906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008085851115611ba0578182fd5b83861115611bac578182fd5b505060208302019391909203915056fe4e6f7420616c6c20436169726f207075626c696320696e707574732077657265207772697474656e2e537461726b576172655f47707353746174656d656e7456657269666965725f323032325f37496e76616c6964207075626c69634d656d6f72795061676573206c656e6774682e4e6f646520737461636b206d75737420636f6e7461696e2065786163746c79206f6e65206974656d2e496e76616c69642076616c7565206f66206e5f6e6f64657320696e2074726565207374727563747572652e53454c45435445445f4255494c54494e535f564543544f525f49535f544f4f5f4c4f4e47496e76616c69642063756d756c61746976652070726f6475637420666f72206d656d6f7279207061676520302e496e636f6e73697374656e742070726f6772616d206f7574707574206c656e6774682e4e6f7420616c6c206d656d6f727920706167657320776572652070726f6365737365642e496e76616c69642076616c7565206f66206e5f706167657320696e2074726565207374727563747572652e5468652073756d206f662074686520706167652073697a657320646f6573206e6f74206d61746368206f75747075742073697a652e496e76616c6964206e756d626572206f6620706169727320696e20746865204d65726b6c652074726565207374727563747572652ea26469706673582212209498f248aa23bb9f9c54cc921137ef3cde9ae3463b7468dd6a63c61a508e2b2e64736f6c634300060c00330000000000000000000000005d07affafc8721ef3dee4d11a2d1484cbf6a9ddf000000000000000000000000fd14567eaf9ba941cb8c8a94eec14831ca7fd1b400000000000000000000000000000000000000000000000000000000000000a00706bd57414b57145b118dd7b92e0d1f040e1a6b6987b842ffb08135699a5ae4068cc8cebf2a51a1025eedd68a01922b720b8a65c3731f3b6df5a524e67ff5160000000000000000000000000000000000000000000000000000000000000008000000000000000000000000217750c27be9147f9e358d9ff26a8224f8acc214000000000000000000000000630a97901ac29590df83f4a64b8d490d54caf2390000000000000000000000008488e8f4e26eba40fae229ab653d98e341cbe57b0000000000000000000000009e614a417f8309575fc11b175a51599661f2bd21000000000000000000000000c879af7d5ed80e4676c203fd300e640c297f31e300000000000000000000000078af2bfb12db15d35f7de8dd77f29c299c78c590000000000000000000000000e9664d230490d5a515ef7ef30033d8075a8d0e2400000000000000000000000003fa911dfca026d9c8edb508851b390accf912e8

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100be5760003560e01c80639b3b76cc11610076578063d6354e151161005b578063d6354e15146102af578063e5b62b29146102b7578063eeb72866146102bf576100be565b80639b3b76cc1461013f578063b7a771f7146102a7576100be565b80634c14a6f9116100a75780634c14a6f9146100fe5780635b4c41c2146101065780636a9385671461010e576100be565b806329e10520146100c35780632f4da80e146100dd575b600080fd5b6100cb61033c565b60408051918252519081900360200190f35b6100e5610341565b6040805192835260208301919091528051918290030190f35b6100cb610387565b6100cb61038c565b61012b6004803603602081101561012457600080fd5b5035610391565b604080519115158252519081900360200190f35b6102a5600480360360a081101561015557600080fd5b81019060208101813564010000000081111561017057600080fd5b82018360208201111561018257600080fd5b803590602001918460208302840111640100000000831117156101a457600080fd5b9193909290916020810190356401000000008111156101c257600080fd5b8201836020820111156101d457600080fd5b803590602001918460208302840111640100000000831117156101f657600080fd5b91939092909160208101903564010000000081111561021457600080fd5b82018360208201111561022657600080fd5b8035906020019184602083028401116401000000008311171561024857600080fd5b91939092909160208101903564010000000081111561026657600080fd5b82018360208201111561027857600080fd5b8035906020019184602083028401116401000000008311171561029a57600080fd5b9193509150356103a2565b005b6100cb610981565b61012b610986565b6100cb61098f565b6102c7610994565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103015781810151838201526020016102e9565b50505050905090810190601f16801561032e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600281565b7f068cc8cebf2a51a1025eedd68a01922b720b8a65c3731f3b6df5a524e67ff5167f0706bd57414b57145b118dd7b92e0d1f040e1a6b6987b842ffb08135699a5ae49091565b600381565b600181565b600061039c826109b4565b92915050565b600354811061041257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f636169726f56657269666965724964206973206f7574206f662072616e67652e604482015290519081900360640190fd5b60006003828154811061042157fe5b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff16915036906104747ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8601828789611b91565b9150915060606000808573ffffffffffffffffffffffffffffffffffffffff16638080fdfb6040518163ffffffff1660e01b8152600401604080518083038186803b1580156104c257600080fd5b505afa1580156104d6573d6000803e3d6000fd5b505050506040513d60408110156104ec57600080fd5b508051602090910151909250905081881161056857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420636169726f417578496e707574206c656e6774682e000000604482015290519081900360640190fd5b61057484838188611b91565b808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250845194975093879350849250151590506105b757fe5b60200260200101519050612710811061063157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c6964206e50616765732e0000000000000000000000000000000000604482015290519081900360640190fd5b8351600482021461068d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611c0b6021913960400191505060405180910390fd5b600080600061069f8f8f8f8f896109c9565b92509250925082876001815181106106b357fe5b60200260200101511461072757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c69642073697a6520666f72206d656d6f7279207061676520302e00604482015290519081900360640190fd5b818760028151811061073557fe5b6020026020010151146107a957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c6964206861736820666f72206d656d6f7279207061676520302e00604482015290519081900360640190fd5b808760038602815181106107b957fe5b602002602001015114610817576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180611ca4602d913960400191505060405180910390fd5b5050505050508373ffffffffffffffffffffffffffffffffffffffff16631cb7dd798e8e8e8e88886040518763ffffffff1660e01b81526004018080602001806020018060200184810384528a8a82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018581038452888152602090810191508990890280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018581038352868152602090810191508790870280828437600081840152601f19601f8201169050808301925050509950505050505050505050600060405180830381600087803b15801561093b57600080fd5b505af115801561094f573d6000803e3d6000fd5b505050506109728989838a8a600881811061096657fe5b9050602002013561141a565b50505050505050505050505050565b606081565b60015460ff1690565b600081565b6060604051806060016040528060258152602001611be660259139905090565b60009081526020819052604090205460ff1690565b600080600080888860008181106109dc57fe5b90506020020135905063400000008110610a5757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c6964206e756d626572206f66207461736b732e0000000000000000604482015290519081900360640190fd5b6002818102610247019450606090850267ffffffffffffffff81118015610a7d57600080fd5b50604051908082528060200260200182016040528015610aa7578160200160208202803683370190505b5090506000610ab4611b53565b60018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634b6cee596040518163ffffffff1660e01b81526004016146406040518083038186803b158015610b1b57600080fd5b505afa158015610b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250614640811015610b5557600080fd5b50905060005b610232811015610bbc5760018101848481518110610b7557fe5b60200260200101818152505081816102328110610b8e57fe5b6020020151848460010181518110610ba257fe5b602090810291909101015260029290920191600101610b5b565b5050600089896006818110610bcd57fe5b9050602002013590506002811015610c4657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f496e76616c696420657865637574696f6e20626567696e20616464726573732e604482015290519081900360640190fd5b60028103838360000181518110610c5957fe5b60200260200101818152505080838360010181518110610c7557fe5b60200260200101818152505060018103838360020181518110610c9457fe5b6020026020010181815250506000838360030181518110610cb157fe5b602002602001018181525050600482019150600060088b8b6007818110610cd457fe5b9050602002013503905060006008905060005b6008811015610dee57808401868681518110610cff57fe5b60209081029190910101528551601086019084830190889083908110610d2157fe5b602090810291909101015260018c1615610d9f578d8d84818110610d4157fe5b90506020020135878760010181518110610d5757fe5b6020026020010181815250508d8d84600101818110610d7257fe5b90506020020135878260010181518110610d8857fe5b602002602001018181525050600283019250610dda565b6000878760010181518110610db057fe5b6020026020010181815250506000878260010181518110610dcd57fe5b6020026020010181815250505b5060019a8b1c9a6002959095019401610ce7565b508915610e46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611c806024913960400191505060405180910390fd5b505050601001600089896008818110610e5b57fe5b90506020020135905080838360000181518110610e7457fe5b6020026020010181815250507f068cc8cebf2a51a1025eedd68a01922b720b8a65c3731f3b6df5a524e67ff516838360010181518110610eb057fe5b60200260200101818152505080600101838360020181518110610ecf57fe5b6020026020010181815250507f0706bd57414b57145b118dd7b92e0d1f040e1a6b6987b842ffb08135699a5ae4838360030181518110610f0b57fe5b60200260200101818152505080600201838360040181518110610f2a57fe5b60200260200101818152505083838360050181518110610f4657fe5b6020026020010181815250506006820191506003810190503660008d8d6001908092610f7493929190611b91565b9150915060005b8681101561115557600083836000818110610f9257fe5b90506020020135905080600211158015610faf5750634000000081105b61101a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c6964207461736b206f75747075742073697a652e00000000000000604482015290519081900360640190fd5b60008484600181811061102957fe5b90506020020135905060008585600281811061104157fe5b9050602002013590508060011115801561105d57506210000081105b6110b2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180611d786035913960400191505060405180910390fd5b868989600001815181106110c257fe5b602002602001018181525050828989600101815181106110de57fe5b602002602001018181525050866001018989600201815181106110fd57fe5b6020026020010181815250508189896003018151811061111957fe5b6020908102919091010152600497909701969582019561114185600360028402018189611b91565b955095505050508080600101915050610f7b565b5080156111c357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c6964206c656e677468206f66207461736b4d657461646174612e00604482015290519081900360640190fd5b828c8c60098181106111d157fe5b905060200201351461122e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611cd16023913960400191505060405180910390fd5b5050508082511461128a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180611bbd6029913960400191505060405180910390fd5b600089897ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81018181106112ba57fe5b90506020020135905060008a8a60018d8d9050038181106112d757fe5b9050602002013590506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663405a63628685857f08000000000000110000000000000000000000000000000000000000000000016040518563ffffffff1660e01b81526004018080602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b838110156113a557818101518382015260200161138d565b5050505090500195505050505050606060405180830381600087803b1580156113cd57600080fd5b505af11580156113e1573d6000803e3d6000fd5b505050506040513d60608110156113f757600080fd5b506020810151604090910151999f909e50989c50979a5050505050505050505050565b60008260008151811061142957fe5b6020026020010151905060008060008787600081811061144557fe5b90506020020135905060608460030167ffffffffffffffff8111801561146a57600080fd5b50604051908082528060200260200182016040528015611494578160200160208202803683370190505b5090506040816001815181106114a657fe5b60209081029190910101526001600587018160606002890267ffffffffffffffff811180156114d457600080fd5b506040519080825280602002602001820160405280156114fe578160200160208202803683370190505b50905060608d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509293506115439250611b73915050565b506000985060808c015b878a10156118575760008085905083600289018151811061156a57fe5b60200260200101519a506000805b8c81101561169d5760008660008360020260038e0101018151811061159957fe5b602002602001015190506210000081106115fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180611d18602b913960400191505060405180910390fd5b60005b8181101561165957600080611619898e8a8e8a6118c0565b91509150808f888e036003018151811061162f57fe5b6020908102919091010152509a8b019a60019a8b019a606098909801979601959384019301611601565b5060008760018460020260038f0101018151811061167357fe5b6020026020010151905080600014611693576116908985836119f9565b93505b5050600101611578565b50806001146116f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180611c2c6029913960400191505060405180910390fd5b60008560018b018151811061170857fe5b6020026020010151905060008660008c018151811061172357fe5b60200260200101519050808860018151811061173b57fe5b60200260200101516002011461179c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180611d436035913960400191505060405180910390fd5b506000876000815181106117ac57fe5b602002602001015190506000828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090508e6002026003018c019b5060007f73b132cb33951232d83dc0f1f81c2d10f9a2598f057404ed02756716092097bb905060208e01868c03848252806040830152826020600383010283a150505061183f81611ae3565b50506001909d019c505050600295909501945061154d565b838b146118af576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611cf46024913960400191505060405180910390fd5b505050505050505050505050505050565b84516020860151604087015190916340000000831061194057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c696420706167652073697a652e0000000000000000000000000000604482015290519081900360640190fd5b8681146119ae57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c6964207061676520616464726573732e0000000000000000000000604482015290519081900360640190fd5b8286018560018660020201815181106119c357fe5b602002602001018181525050818560008660020201815181106119e257fe5b602002602001018181525050509550959350505050565b600082821115611a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180611c55602b913960400191505060405180910390fd5b60008460018086036002020181518110611a6a57fe5b6020026020010151905060008385039050600060028202602002602001905060006040860282890120905083886001856002020181518110611aa857fe5b60200260200101818152505080600101886000856002020181518110611aca57fe5b6020908102919091010152505060010195945050505050565b600081815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091555460ff16611b5057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016811790555b50565b604051806146400160405280610232906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008085851115611ba0578182fd5b83861115611bac578182fd5b505060208302019391909203915056fe4e6f7420616c6c20436169726f207075626c696320696e707574732077657265207772697474656e2e537461726b576172655f47707353746174656d656e7456657269666965725f323032325f37496e76616c6964207075626c69634d656d6f72795061676573206c656e6774682e4e6f646520737461636b206d75737420636f6e7461696e2065786163746c79206f6e65206974656d2e496e76616c69642076616c7565206f66206e5f6e6f64657320696e2074726565207374727563747572652e53454c45435445445f4255494c54494e535f564543544f525f49535f544f4f5f4c4f4e47496e76616c69642063756d756c61746976652070726f6475637420666f72206d656d6f7279207061676520302e496e636f6e73697374656e742070726f6772616d206f7574707574206c656e6774682e4e6f7420616c6c206d656d6f727920706167657320776572652070726f6365737365642e496e76616c69642076616c7565206f66206e5f706167657320696e2074726565207374727563747572652e5468652073756d206f662074686520706167652073697a657320646f6573206e6f74206d61746368206f75747075742073697a652e496e76616c6964206e756d626572206f6620706169727320696e20746865204d65726b6c652074726565207374727563747572652ea26469706673582212209498f248aa23bb9f9c54cc921137ef3cde9ae3463b7468dd6a63c61a508e2b2e64736f6c634300060c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000005d07affafc8721ef3dee4d11a2d1484cbf6a9ddf000000000000000000000000fd14567eaf9ba941cb8c8a94eec14831ca7fd1b400000000000000000000000000000000000000000000000000000000000000a00706bd57414b57145b118dd7b92e0d1f040e1a6b6987b842ffb08135699a5ae4068cc8cebf2a51a1025eedd68a01922b720b8a65c3731f3b6df5a524e67ff5160000000000000000000000000000000000000000000000000000000000000008000000000000000000000000217750c27be9147f9e358d9ff26a8224f8acc214000000000000000000000000630a97901ac29590df83f4a64b8d490d54caf2390000000000000000000000008488e8f4e26eba40fae229ab653d98e341cbe57b0000000000000000000000009e614a417f8309575fc11b175a51599661f2bd21000000000000000000000000c879af7d5ed80e4676c203fd300e640c297f31e300000000000000000000000078af2bfb12db15d35f7de8dd77f29c299c78c590000000000000000000000000e9664d230490d5a515ef7ef30033d8075a8d0e2400000000000000000000000003fa911dfca026d9c8edb508851b390accf912e8

-----Decoded View---------------
Arg [0] : bootloaderProgramContract (address): 0x5d07afFAfc8721Ef3dEe4D11A2D1484CBf6A9dDf
Arg [1] : memoryPageFactRegistry_ (address): 0xFD14567eaf9ba941cB8c8a94eEC14831ca7fD1b4
Arg [2] : cairoVerifierContracts (address[]): 0x217750c27bE9147f9e358D9FF26a8224F8aCC214,0x630A97901Ac29590DF83f4A64B8D490D54caf239,0x8488e8f4e26eBa40faE229AB653d98E341cbE57B,0x9E614a417f8309575fC11b175A51599661f2Bd21,0xC879aF7D5eD80e4676C203FD300E640C297F31e3,0x78Af2BFB12Db15d35f7dE8DD77f29C299C78c590,0xe9664D230490d5A515ef7Ef30033d8075a8D0E24,0x03Fa911dfCa026D9C8Edb508851b390accF912e8
Arg [3] : hashedSupportedCairoVerifiers (uint256): 3178097804922730583543126053422762895998573737925004508949311089390705597156
Arg [4] : simpleBootloaderProgramHash (uint256): 2962621603719000361370283216422448934312521782617806945663080079725495842070

-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 0000000000000000000000005d07affafc8721ef3dee4d11a2d1484cbf6a9ddf
Arg [1] : 000000000000000000000000fd14567eaf9ba941cb8c8a94eec14831ca7fd1b4
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0706bd57414b57145b118dd7b92e0d1f040e1a6b6987b842ffb08135699a5ae4
Arg [4] : 068cc8cebf2a51a1025eedd68a01922b720b8a65c3731f3b6df5a524e67ff516
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [6] : 000000000000000000000000217750c27be9147f9e358d9ff26a8224f8acc214
Arg [7] : 000000000000000000000000630a97901ac29590df83f4a64b8d490d54caf239
Arg [8] : 0000000000000000000000008488e8f4e26eba40fae229ab653d98e341cbe57b
Arg [9] : 0000000000000000000000009e614a417f8309575fc11b175a51599661f2bd21
Arg [10] : 000000000000000000000000c879af7d5ed80e4676c203fd300e640c297f31e3
Arg [11] : 00000000000000000000000078af2bfb12db15d35f7de8dd77f29c299c78c590
Arg [12] : 000000000000000000000000e9664d230490d5a515ef7ef30033d8075a8d0e24
Arg [13] : 00000000000000000000000003fa911dfca026d9c8edb508851b390accf912e8


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.