Address Details
contract

0x55E6Bd7ef032f3D8B2664B21E6EADF2B47A9bf10

Contract Name
WithdrawVerifier
Creator
0x25f72e–df3745 at 0x8715b2–57d675
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
24063658
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
WithdrawVerifier




Optimization enabled
true
Compiler version
v0.8.3+commit.8d00100c




Optimization runs
200
EVM Version
istanbul




Verified at
2021-10-20T03:28:02.974609Z

Contract source code

// SPDX-License-Identifier: GPL-3.0
/*
    Copyright 2021 0KIMS association.

    This file is generated with [snarkJS](https://github.com/iden3/snarkjs).

    snarkJS is a free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    snarkJS is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
    License for more details.

    You should have received a copy of the GNU General Public License
    along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
*/


pragma solidity >=0.7.0 <0.9.0;

contract WithdrawVerifier {
    
    uint32 constant n =   8192;
    uint16 constant nPublic =  6;
    uint16 constant nLagrange = 6;
    
    uint256 constant Qmx = 9812990417891785149290853635884756604156925564429501791023176706534578654756;
    uint256 constant Qmy = 21783261496952229773068775145495989642092856536096059569224598705830038301860;
    uint256 constant Qlx = 4862569108601205547519388150221113650377056086643956065875631706522397703601;
    uint256 constant Qly = 12315787432543705786329072036255167053267284545546692315456743652579454667888;
    uint256 constant Qrx = 13346569727173239706080242910175284835144894727041218425529748182362840825680;
    uint256 constant Qry = 12412014216675284398817932643280922650738672273695597101791421236450379231553;
    uint256 constant Qox = 15246995584395848292127611626629639780522722553918254829267854394612001503688;
    uint256 constant Qoy = 4735032615497106247010267919244985892651438700479267612922851925980099754939;
    uint256 constant Qcx = 13817462705582723216926558160264393636147387531465034262210194411906615810562;
    uint256 constant Qcy = 11672296671516409346477277497494210250772049820088424582673825053903043378206;
    uint256 constant S1x = 18010578473107001911194954689672873895600146975978853155759666449922440622615;
    uint256 constant S1y = 8796436180464952119042498632500744654768422256099751727780243036468042776025;
    uint256 constant S2x = 10437044351743733960902126064430106837567773777909483816842955823917440584685;
    uint256 constant S2y = 1053129540443698952758538755518775583043236479776237775249506957724086383752;
    uint256 constant S3x = 9238726063826290257633503344688672073637924248460056731534547065675800581673;
    uint256 constant S3y = 8417284805985257806141282660737437020206447364384651342522568107013632925549;
    uint256 constant k1 = 2;
    uint256 constant k2 = 3;
    uint256 constant X2x1 = 21831381940315734285607113342023901060522397560371972897001948545212302161822;
    uint256 constant X2x2 = 17231025384763736816414546592865244497437017442647097510447326538965263639101;
    uint256 constant X2y1 = 2388026358213174446665280700919698872609886601280537296205114254867301080648;
    uint256 constant X2y2 = 11507326595632554467052522095592665270651932854513688777769618397986436103170;
    
    uint256 constant q = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
    uint256 constant qf = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    uint256 constant w1 = 197302210312744933010843010704445784068657690384188106020011018676818793232;    
    
    uint256 constant G1x = 1;
    uint256 constant G1y = 2;
    uint256 constant G2x1 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
    uint256 constant G2x2 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
    uint256 constant G2y1 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
    uint256 constant G2y2 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
    uint16 constant pA = 32;
    uint16 constant pB = 96;
    uint16 constant pC = 160;
    uint16 constant pZ = 224;
    uint16 constant pT1 = 288;
    uint16 constant pT2 = 352;
    uint16 constant pT3 = 416;
    uint16 constant pWxi = 480;
    uint16 constant pWxiw = 544;
    uint16 constant pEval_a = 608;
    uint16 constant pEval_b = 640;
    uint16 constant pEval_c = 672;
    uint16 constant pEval_s1 = 704;
    uint16 constant pEval_s2 = 736;
    uint16 constant pEval_zw = 768;
    uint16 constant pEval_r = 800;
    
    uint16 constant pAlpha = 0;
    uint16 constant pBeta = 32;
    uint16 constant pGamma = 64;
    uint16 constant pXi = 96;
    uint16 constant pXin = 128;
    uint16 constant pBetaXi = 160;
    uint16 constant pV1 = 192;
    uint16 constant pV2 = 224;
    uint16 constant pV3 = 256;
    uint16 constant pV4 = 288;
    uint16 constant pV5 = 320;
    uint16 constant pV6 = 352;
    uint16 constant pU = 384;
    uint16 constant pPl = 416;
    uint16 constant pEval_t = 448;
    uint16 constant pA1 = 480;
    uint16 constant pB1 = 544;
    uint16 constant pZh = 608;
    uint16 constant pZhInv = 640;
    
    uint16 constant pEval_l1 = 672;
    
    uint16 constant pEval_l2 = 704;
    
    uint16 constant pEval_l3 = 736;
    
    uint16 constant pEval_l4 = 768;
    
    uint16 constant pEval_l5 = 800;
    
    uint16 constant pEval_l6 = 832;
    
    
    
    uint16 constant lastMem = 864;


    function verifyProof(bytes memory proof, uint[] memory pubSignals) external view returns (bool) {
        assembly {
            /////////
            // Computes the inverse using the extended euclidean algorithm
            /////////
            function inverse(a, q) -> inv {
                let t := 0     
                let newt := 1
                let r := q     
                let newr := a
                let quotient
                let aux
                
                for { } newr { } {
                    quotient := sdiv(r, newr)
                    aux := sub(t, mul(quotient, newt))
                    t:= newt
                    newt:= aux
                    
                    aux := sub(r,mul(quotient, newr))
                    r := newr
                    newr := aux
                }
                
                if gt(r, 1) { revert(0,0) }
                if slt(t, 0) { t:= add(t, q) }

                inv := t
            }
            
            ///////
            // Computes the inverse of an array of values
            // See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
            //////
            function inverseArray(pVals, n) {
    
                let pAux := mload(0x40)     // Point to the next free position
                let pIn := pVals
                let lastPIn := add(pVals, mul(n, 32))  // Read n elemnts
                let acc := mload(pIn)       // Read the first element
                pIn := add(pIn, 32)         // Point to the second element
                let inv
    
                
                for { } lt(pIn, lastPIn) { 
                    pAux := add(pAux, 32) 
                    pIn := add(pIn, 32)
                } 
                {
                    mstore(pAux, acc)
                    acc := mulmod(acc, mload(pIn), q)
                }
                acc := inverse(acc, q)
                
                // At this point pAux pint to the next free position we substract 1 to point to the last used
                pAux := sub(pAux, 32)
                // pIn points to the n+1 element, we substract to point to n
                pIn := sub(pIn, 32)
                lastPIn := pVals  // We don't process the first element 
                for { } gt(pIn, lastPIn) { 
                    pAux := sub(pAux, 32) 
                    pIn := sub(pIn, 32)
                } 
                {
                    inv := mulmod(acc, mload(pAux), q)
                    acc := mulmod(acc, mload(pIn), q)
                    mstore(pIn, inv)
                }
                // pIn points to first element, we just set it.
                mstore(pIn, acc)
            }
            
            function checkField(v) {
                if iszero(lt(v, q)) {
                    mstore(0, 0)
                    return(0,0x20)
                }
            }
            
            function checkInput(pProof) {
                if iszero(eq(mload(pProof), 800 )) {
                    mstore(0, 0)
                    return(0,0x20)
                }
                checkField(mload(add(pProof, pEval_a)))
                checkField(mload(add(pProof, pEval_b)))
                checkField(mload(add(pProof, pEval_c)))
                checkField(mload(add(pProof, pEval_s1)))
                checkField(mload(add(pProof, pEval_s2)))
                checkField(mload(add(pProof, pEval_zw)))
                checkField(mload(add(pProof, pEval_r)))

                // Points are checked in the point operations precompiled smart contracts
            }
            
            function calculateChallanges(pProof, pMem) {
            
                let a
                let b
                
                b := mod(keccak256(add(pProof, pA), 192), q) 
                mstore( add(pMem, pBeta), b)
                mstore( add(pMem, pGamma), mod(keccak256(add(pMem, pBeta), 32), q))
                mstore( add(pMem, pAlpha), mod(keccak256(add(pProof, pZ), 64), q))
                
                a := mod(keccak256(add(pProof, pT1), 192), q)
                mstore( add(pMem, pXi), a)
                mstore( add(pMem, pBetaXi), mulmod(b, a, q))
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                a:= mulmod(a, a, q)
                
                mstore( add(pMem, pXin), a)
                a:= mod(add(sub(a, 1),q), q)
                mstore( add(pMem, pZh), a)
                mstore( add(pMem, pZhInv), a)  // We will invert later together with lagrange pols
                
                let v1 := mod(keccak256(add(pProof, pEval_a), 224), q)
                mstore( add(pMem, pV1), v1)
                a := mulmod(v1, v1, q)
                mstore( add(pMem, pV2), a)
                a := mulmod(a, v1, q)
                mstore( add(pMem, pV3), a)
                a := mulmod(a, v1, q)
                mstore( add(pMem, pV4), a)
                a := mulmod(a, v1, q)
                mstore( add(pMem, pV5), a)
                a := mulmod(a, v1, q)
                mstore( add(pMem, pV6), a)
                
                mstore( add(pMem, pU), mod(keccak256(add(pProof, pWxi), 128), q))
            }
            
            function calculateLagrange(pMem) {

                let w := 1                
                
                mstore(
                    add(pMem, pEval_l1), 
                    mulmod(
                        n, 
                        mod(
                            add(
                                sub(
                                    mload(add(pMem, pXi)), 
                                    w
                                ), 
                                q
                            ),
                            q
                        ), 
                        q
                    )
                )
                
                w := mulmod(w, w1, q)
                
                
                mstore(
                    add(pMem, pEval_l2), 
                    mulmod(
                        n, 
                        mod(
                            add(
                                sub(
                                    mload(add(pMem, pXi)), 
                                    w
                                ), 
                                q
                            ),
                            q
                        ), 
                        q
                    )
                )
                
                w := mulmod(w, w1, q)
                
                
                mstore(
                    add(pMem, pEval_l3), 
                    mulmod(
                        n, 
                        mod(
                            add(
                                sub(
                                    mload(add(pMem, pXi)), 
                                    w
                                ), 
                                q
                            ),
                            q
                        ), 
                        q
                    )
                )
                
                w := mulmod(w, w1, q)
                
                
                mstore(
                    add(pMem, pEval_l4), 
                    mulmod(
                        n, 
                        mod(
                            add(
                                sub(
                                    mload(add(pMem, pXi)), 
                                    w
                                ), 
                                q
                            ),
                            q
                        ), 
                        q
                    )
                )
                
                w := mulmod(w, w1, q)
                
                
                mstore(
                    add(pMem, pEval_l5), 
                    mulmod(
                        n, 
                        mod(
                            add(
                                sub(
                                    mload(add(pMem, pXi)), 
                                    w
                                ), 
                                q
                            ),
                            q
                        ), 
                        q
                    )
                )
                
                w := mulmod(w, w1, q)
                
                
                mstore(
                    add(pMem, pEval_l6), 
                    mulmod(
                        n, 
                        mod(
                            add(
                                sub(
                                    mload(add(pMem, pXi)), 
                                    w
                                ), 
                                q
                            ),
                            q
                        ), 
                        q
                    )
                )
                
                
                
                inverseArray(add(pMem, pZhInv), 7 )
                
                let zh := mload(add(pMem, pZh))
                w := 1
                
                
                mstore(
                    add(pMem, pEval_l1 ), 
                    mulmod(
                        mload(add(pMem, pEval_l1 )),
                        zh,
                        q
                    )
                )
                
                
                w := mulmod(w, w1, q)
                
                
                
                mstore(
                    add(pMem, pEval_l2), 
                    mulmod(
                        w,
                        mulmod(
                            mload(add(pMem, pEval_l2)),
                            zh,
                            q
                        ),
                        q
                    )
                )
                
                
                w := mulmod(w, w1, q)
                
                
                
                mstore(
                    add(pMem, pEval_l3), 
                    mulmod(
                        w,
                        mulmod(
                            mload(add(pMem, pEval_l3)),
                            zh,
                            q
                        ),
                        q
                    )
                )
                
                
                w := mulmod(w, w1, q)
                
                
                
                mstore(
                    add(pMem, pEval_l4), 
                    mulmod(
                        w,
                        mulmod(
                            mload(add(pMem, pEval_l4)),
                            zh,
                            q
                        ),
                        q
                    )
                )
                
                
                w := mulmod(w, w1, q)
                
                
                
                mstore(
                    add(pMem, pEval_l5), 
                    mulmod(
                        w,
                        mulmod(
                            mload(add(pMem, pEval_l5)),
                            zh,
                            q
                        ),
                        q
                    )
                )
                
                
                w := mulmod(w, w1, q)
                
                
                
                mstore(
                    add(pMem, pEval_l6), 
                    mulmod(
                        w,
                        mulmod(
                            mload(add(pMem, pEval_l6)),
                            zh,
                            q
                        ),
                        q
                    )
                )
                
                
                


            }
            
            function calculatePl(pMem, pPub) {
                let pl := 0
                
                 
                pl := mod(
                    add(
                        sub(
                            pl,  
                            mulmod(
                                mload(add(pMem, pEval_l1)),
                                mload(add(pPub, 32)),
                                q
                            )
                        ),
                        q
                    ),
                    q
                )
                 
                pl := mod(
                    add(
                        sub(
                            pl,  
                            mulmod(
                                mload(add(pMem, pEval_l2)),
                                mload(add(pPub, 64)),
                                q
                            )
                        ),
                        q
                    ),
                    q
                )
                 
                pl := mod(
                    add(
                        sub(
                            pl,  
                            mulmod(
                                mload(add(pMem, pEval_l3)),
                                mload(add(pPub, 96)),
                                q
                            )
                        ),
                        q
                    ),
                    q
                )
                 
                pl := mod(
                    add(
                        sub(
                            pl,  
                            mulmod(
                                mload(add(pMem, pEval_l4)),
                                mload(add(pPub, 128)),
                                q
                            )
                        ),
                        q
                    ),
                    q
                )
                 
                pl := mod(
                    add(
                        sub(
                            pl,  
                            mulmod(
                                mload(add(pMem, pEval_l5)),
                                mload(add(pPub, 160)),
                                q
                            )
                        ),
                        q
                    ),
                    q
                )
                 
                pl := mod(
                    add(
                        sub(
                            pl,  
                            mulmod(
                                mload(add(pMem, pEval_l6)),
                                mload(add(pPub, 192)),
                                q
                            )
                        ),
                        q
                    ),
                    q
                )
                
                
                mstore(add(pMem, pPl), pl)
                

            }

            function calculateT(pProof, pMem) {
                let t
                let t1
                let t2
                t := addmod(
                    mload(add(pProof, pEval_r)), 
                    mload(add(pMem, pPl)), 
                    q
                )
                
                t1 := mulmod(
                    mload(add(pProof, pEval_s1)),
                    mload(add(pMem, pBeta)),
                    q
                )

                t1 := addmod(
                    t1,
                    mload(add(pProof, pEval_a)),
                    q
                )
                
                t1 := addmod(
                    t1,
                    mload(add(pMem, pGamma)),
                    q
                )

                t2 := mulmod(
                    mload(add(pProof, pEval_s2)),
                    mload(add(pMem, pBeta)),
                    q
                )

                t2 := addmod(
                    t2,
                    mload(add(pProof, pEval_b)),
                    q
                )
                
                t2 := addmod(
                    t2,
                    mload(add(pMem, pGamma)),
                    q
                )
                
                t1 := mulmod(t1, t2, q)
                
                t2 := addmod(
                    mload(add(pProof, pEval_c)),
                    mload(add(pMem, pGamma)),
                    q
                )

                t1 := mulmod(t1, t2, q)
                t1 := mulmod(t1, mload(add(pProof, pEval_zw)), q)
                t1 := mulmod(t1, mload(add(pMem, pAlpha)), q)
                
                t2 := mulmod(
                    mload(add(pMem, pEval_l1)), 
                    mload(add(pMem, pAlpha)), 
                    q
                )

                t2 := mulmod(
                    t2, 
                    mload(add(pMem, pAlpha)), 
                    q
                )

                t1 := addmod(t1, t2, q)
                
                t := mod(sub(add(t, q), t1), q)
                t := mulmod(t, mload(add(pMem, pZhInv)), q)
                
                mstore( add(pMem, pEval_t) , t)

            }
            
            function g1_set(pR, pP) {
                mstore(pR, mload(pP))
                mstore(add(pR, 32), mload(add(pP,32)))
            }

            function g1_acc(pR, pP) {
                let mIn := mload(0x40)
                mstore(mIn, mload(pR))
                mstore(add(mIn,32), mload(add(pR, 32)))
                mstore(add(mIn,64), mload(pP))
                mstore(add(mIn,96), mload(add(pP, 32)))

                let success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
                
                if iszero(success) {
                    mstore(0, 0)
                    return(0,0x20)
                }
            }

            function g1_mulAcc(pR, pP, s) {
                let success
                let mIn := mload(0x40)
                mstore(mIn, mload(pP))
                mstore(add(mIn,32), mload(add(pP, 32)))
                mstore(add(mIn,64), s)

                success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
                
                if iszero(success) {
                    mstore(0, 0)
                    return(0,0x20)
                }
                
                mstore(add(mIn,64), mload(pR))
                mstore(add(mIn,96), mload(add(pR, 32)))

                success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
                
                if iszero(success) {
                    mstore(0, 0)
                    return(0,0x20)
                }
                
            }

            function g1_mulAccC(pR, x, y, s) {
                let success
                let mIn := mload(0x40)
                mstore(mIn, x)
                mstore(add(mIn,32), y)
                mstore(add(mIn,64), s)

                success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
                
                if iszero(success) {
                    mstore(0, 0)
                    return(0,0x20)
                }
                
                mstore(add(mIn,64), mload(pR))
                mstore(add(mIn,96), mload(add(pR, 32)))

                success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
                
                if iszero(success) {
                    mstore(0, 0)
                    return(0,0x20)
                }
            }

            function g1_mulSetC(pR, x, y, s) {
                let success
                let mIn := mload(0x40)
                mstore(mIn, x)
                mstore(add(mIn,32), y)
                mstore(add(mIn,64), s)

                success := staticcall(sub(gas(), 2000), 7, mIn, 96, pR, 64)
                
                if iszero(success) {
                    mstore(0, 0)
                    return(0,0x20)
                }
            }


            function calculateA1(pProof, pMem) {
                let p := add(pMem, pA1)
                g1_set(p, add(pProof, pWxi))
                g1_mulAcc(p, add(pProof, pWxiw), mload(add(pMem, pU)))
            }
            
            
            function calculateB1(pProof, pMem) {
                let s
                let s1
                let p := add(pMem, pB1)
                
                // Calculate D
                s := mulmod( mload(add(pProof, pEval_a)), mload(add(pMem, pV1)), q)
                g1_mulSetC(p, Qlx, Qly, s)

                s := mulmod( s, mload(add(pProof, pEval_b)), q)                
                g1_mulAccC(p, Qmx, Qmy, s)

                s := mulmod( mload(add(pProof, pEval_b)), mload(add(pMem, pV1)), q)
                g1_mulAccC(p, Qrx, Qry, s)
                
                s := mulmod( mload(add(pProof, pEval_c)), mload(add(pMem, pV1)), q)
                g1_mulAccC(p, Qox, Qoy, s)

                s :=mload(add(pMem, pV1))
                g1_mulAccC(p, Qcx, Qcy, s)

                s := addmod(mload(add(pProof, pEval_a)), mload(add(pMem, pBetaXi)), q)
                s := addmod(s, mload(add(pMem, pGamma)), q)
                s1 := mulmod(k1, mload(add(pMem, pBetaXi)), q)
                s1 := addmod(s1, mload(add(pProof, pEval_b)), q)
                s1 := addmod(s1, mload(add(pMem, pGamma)), q)
                s := mulmod(s, s1, q)
                s1 := mulmod(k2, mload(add(pMem, pBetaXi)), q)
                s1 := addmod(s1, mload(add(pProof, pEval_c)), q)
                s1 := addmod(s1, mload(add(pMem, pGamma)), q)
                s := mulmod(s, s1, q)
                s := mulmod(s, mload(add(pMem, pAlpha)), q)
                s := mulmod(s, mload(add(pMem, pV1)), q)
                s1 := mulmod(mload(add(pMem, pEval_l1)), mload(add(pMem, pAlpha)), q)
                s1 := mulmod(s1, mload(add(pMem, pAlpha)), q)
                s1 := mulmod(s1, mload(add(pMem, pV1)), q)
                s := addmod(s, s1, q)
                s := addmod(s, mload(add(pMem, pU)), q)
                g1_mulAcc(p, add(pProof, pZ), s)
                
                s := mulmod(mload(add(pMem, pBeta)), mload(add(pProof, pEval_s1)), q)
                s := addmod(s, mload(add(pProof, pEval_a)), q)
                s := addmod(s, mload(add(pMem, pGamma)), q)
                s1 := mulmod(mload(add(pMem, pBeta)), mload(add(pProof, pEval_s2)), q)
                s1 := addmod(s1, mload(add(pProof, pEval_b)), q)
                s1 := addmod(s1, mload(add(pMem, pGamma)), q)
                s := mulmod(s, s1, q)
                s := mulmod(s, mload(add(pMem, pAlpha)), q)
                s := mulmod(s, mload(add(pMem, pV1)), q)
                s := mulmod(s, mload(add(pMem, pBeta)), q)
                s := mulmod(s, mload(add(pProof, pEval_zw)), q)
                s := mod(sub(q, s), q)
                g1_mulAccC(p, S3x, S3y, s)


                // calculate F
                g1_acc(p , add(pProof, pT1))

                s := mload(add(pMem, pXin))
                g1_mulAcc(p, add(pProof, pT2), s)
                
                s := mulmod(s, s, q)
                g1_mulAcc(p, add(pProof, pT3), s)
                
                g1_mulAcc(p, add(pProof, pA), mload(add(pMem, pV2)))
                g1_mulAcc(p, add(pProof, pB), mload(add(pMem, pV3)))
                g1_mulAcc(p, add(pProof, pC), mload(add(pMem, pV4)))
                g1_mulAccC(p, S1x, S1y, mload(add(pMem, pV5)))
                g1_mulAccC(p, S2x, S2y, mload(add(pMem, pV6)))
                
                // calculate E
                s := mload(add(pMem, pEval_t))
                s := addmod(s, mulmod(mload(add(pProof, pEval_r)), mload(add(pMem, pV1)), q), q)
                s := addmod(s, mulmod(mload(add(pProof, pEval_a)), mload(add(pMem, pV2)), q), q)
                s := addmod(s, mulmod(mload(add(pProof, pEval_b)), mload(add(pMem, pV3)), q), q)
                s := addmod(s, mulmod(mload(add(pProof, pEval_c)), mload(add(pMem, pV4)), q), q)
                s := addmod(s, mulmod(mload(add(pProof, pEval_s1)), mload(add(pMem, pV5)), q), q)
                s := addmod(s, mulmod(mload(add(pProof, pEval_s2)), mload(add(pMem, pV6)), q), q)
                s := addmod(s, mulmod(mload(add(pProof, pEval_zw)), mload(add(pMem, pU)), q), q)
                s := mod(sub(q, s), q)
                g1_mulAccC(p, G1x, G1y, s)
                
                
                // Last part of B
                s := mload(add(pMem, pXi))
                g1_mulAcc(p, add(pProof, pWxi), s)

                s := mulmod(mload(add(pMem, pU)), mload(add(pMem, pXi)), q)
                s := mulmod(s, w1, q)
                g1_mulAcc(p, add(pProof, pWxiw), s)

            }
            
            function checkPairing(pMem) -> isOk {
                let mIn := mload(0x40)
                mstore(mIn, mload(add(pMem, pA1)))
                mstore(add(mIn,32), mload(add(add(pMem, pA1), 32)))
                mstore(add(mIn,64), X2x2)
                mstore(add(mIn,96), X2x1)
                mstore(add(mIn,128), X2y2)
                mstore(add(mIn,160), X2y1)
                mstore(add(mIn,192), mload(add(pMem, pB1)))
                let s := mload(add(add(pMem, pB1), 32))
                s := mod(sub(qf, s), qf)
                mstore(add(mIn,224), s)
                mstore(add(mIn,256), G2x2)
                mstore(add(mIn,288), G2x1)
                mstore(add(mIn,320), G2y2)
                mstore(add(mIn,352), G2y1)
                
                let success := staticcall(sub(gas(), 2000), 8, mIn, 384, mIn, 0x20)
                
                isOk := and(success, mload(mIn))
            }
            
            let pMem := mload(0x40)
            mstore(0x40, add(pMem, lastMem))
            
            checkInput(proof)
            calculateChallanges(proof, pMem)
            calculateLagrange(pMem)
            calculatePl(pMem, pubSignals)
            calculateT(proof, pMem)
            calculateA1(proof, pMem)
            calculateB1(proof, pMem)
            let isValid := checkPairing(pMem)
            
            mstore(0x40, sub(pMem, lastMem))
            mstore(0, isValid)
            return(0,0x20)
        }
        
    }
}
        

Contract ABI

[{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verifyProof","inputs":[{"type":"bytes","name":"proof","internalType":"bytes"},{"type":"uint256[]","name":"pubSignals","internalType":"uint256[]"}]}]
              

Contract Creation Code

0x608060405234801561001057600080fd5b5061183b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80631e8e1e1314610030575b600080fd5b61004361003e3660046116cf565b610057565b604051901515815260200160405180910390f35b60006115e0565b600080600184846000805b821561008b575092938183058581029091039350909181830290039081610069565b505050600181111561009c57600080fd5b505060008112156100aa5783015b9392505050565b60405181602084028301815160208301925060005b828410156100f7578185526000805160206117c68339815191528451830991506020850194506020840193506100c6565b61010f6000805160206117c68339815191528361005e565b91506020850394506020840393508592505b82841115610166576000805160206117c68339815191528551830990506000805160206117c683398151915284518309818552601f1995860195909401939150610121565b5090915250505050565b6000805160206117c6833981519152811061018f576000805260206000f35b50565b6103208151146101a6576000805260206000f35b6101b4610260820151610170565b6101c2610280820151610170565b6101d06102a0820151610170565b6101de6102c0820151610170565b6101ec6102e0820151610170565b6101fa610300820151610170565b61018f610320820151610170565b6000806000805160206117c683398151915260c060208501200690508060208501526000805160206117c68339815191526020808601200660408501526000805160206117c6833981519152604060e08501200660008501526000805160206117c683398151915260c06101208501200691508160608501526000805160206117c683398151915282820960a0850152506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990508060808401526000805160206117c683398151915280600183030106905080610260840152806102808401526000805160206117c683398151915260e0610260840120068060c08501526000805160206117c683398151915281820991508160e08501526000805160206117c68339815191528183099150816101008501526000805160206117c68339815191528183099150816101208501526000805160206117c68339815191528183099150816101408501526000805160206117c6833981519152818309610160850152505060806101e091909101206000805160206117c6833981519152900661018090910152565b60016000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096102a08301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096102c08301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096102e08301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096103008301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096103208301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c683398151915283606086015103010661200009610340830152610677600761028084016100b1565b610260820151600191506000805160206117c6833981519152816102a0850151096102a08401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826102c08601510983096102c08401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826102e08601510983096102e08401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826103008601510983096103008401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826103208601510983096103208401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c68339815191528082610340860151098309610340840152505050565b60006000805160206117c6833981519152806000805160206117c683398151915260208601516102a0860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260408601516102c0860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260608601516102e0860151098303010690506000805160206117c6833981519152806000805160206117c68339815191526080860151610300860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260a0860151610320860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260c086015161034086015109830301069050806101a0830152505050565b60008060006000805160206117c68339815191526101a08601516103208601510892506000805160206117c683398151915260208601516102c08601510991506000805160206117c6833981519152610260850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915260208601516102e08601510990506000805160206117c6833981519152610280850151820890506000805160206117c68339815191526040860151820890506000805160206117c683398151915281830991506000805160206117c683398151915260408601516102a08601510890506000805160206117c683398151915281830991506000805160206117c6833981519152610300850151830991506000805160206117c68339815191526000860151830991506000805160206117c683398151915260008601516102a08701510990506000805160206117c68339815191526000860151820990506000805160206117c68339815191528183089150506000805160206117c6833981519152816000805160206117c6833981519152840103069150506000805160206117c683398151915261028084015182099050806101c0840152505050565b6040518151815260208201516020820152825160408201526020830151606082015260408260808360066107d05a03fa905080610b2c576000805260206000f35b505050565b6000604051835181526020840151602082015284604082015260408160608360076107d05a03fa915081610b69576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa91505080610b9a576000805260206000f35b50505050565b600060405183815284602082015285604082015260408160608360076107d05a03fa915081610bd3576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa91505080610c04576000805260206000f35b5050505050565b600060405183815284602082015285604082015260408360608360076107d05a03fa91505080610c04576000805260206000f35b6101e08201610c5c6101e083018281518152602091820151910152565b610b2c610180840151610220840183610b31565b60008061022084016000805160206117c683398151915260c0860151610260860151099250610ce1837f1b3a7d18f4188ca119d369d1d8be9c235f69bb9ce28f39266e021bc817b2cc707f0ac01dd875295d875318e5463b080e9c5e1f51a342b9faba59c7b7d8533bfdb184610c0b565b6000805160206117c683398151915261028085015184099250610d46837f3028e39b43e930fb20aaff14a85a8843e2db479338d42d1690984a0728836ca47f15b1f4ac25954cd7ffefdd381eed2712796783067e53d79f97220442f6690e2484610ba0565b6000805160206117c683398151915260c0860151610280860151099250610daf837f1b70f37abfc61e9b7d4eb6879d77d24fdf22158e3f7f414cc55eae2d7768f1417f1d81e40939e1600e3b1e0a0673f6ad2f8fd4cd1b9c4e83063e2ca4649b9aff5084610ba0565b6000805160206117c683398151915260c08601516102a0860151099250610e18837f0a77eef902d5c151c65ad12ded8b324255b9bf602ccf59dfb438bb5b626dbbbb7f21b57e6202ee690deadbe4d1c167009146bc5b28812b686d2968b286e1c779c884610ba0565b60c08501519250610e6b837f19ce492a10fd9cc297fade9bf6fc9094bf4a1b5fada98d93ee79774be1173c1e7f1e8c68208b5ec751a2a75fadf90361c33b6820e451ebf87942a9ebdc0bb91a0284610ba0565b6000805160206117c683398151915260a08601516102608601510892506000805160206117c68339815191526040860151840892506000805160206117c683398151915260a086015160020991506000805160206117c6833981519152610280850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915282840992506000805160206117c683398151915260a086015160030991506000805160206117c68339815191526102a0850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915282840992506000805160206117c68339815191526000860151840992506000805160206117c683398151915260c0860151840992506000805160206117c683398151915260008601516102a08701510991506000805160206117c68339815191526000860151830991506000805160206117c683398151915260c0860151830991506000805160206117c683398151915282840892506000805160206117c6833981519152610180860151840892506110148360e0860183610b31565b6000805160206117c68339815191526102c085015160208701510992506000805160206117c6833981519152610260850151840892506000805160206117c68339815191526040860151840892506000805160206117c68339815191526102e085015160208701510991506000805160206117c6833981519152610280850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915282840992506000805160206117c68339815191526000860151840992506000805160206117c683398151915260c0860151840992506000805160206117c68339815191526020860151840992506000805160206117c683398151915261030085015184096000805160206117c6833981519152908103069250611184837f129c03adbe966f898444048c9f7e5447371ab4ce76b5f83cb1d25309cca79f6d7f146cef0367944d5e41e44bd661a3591c4af7cee6f0a6f26f60cb29d9605f162984610ba0565b611192610120850182610aeb565b608085015192506111a883610160860183610b31565b6000805160206117c683398151915283840992506111cb836101a0860183610b31565b6111dd60e08601516020860183610b31565b6111f06101008601516060860183610b31565b61120361012086015160a0860183610b31565b6112546101408601517f13729b3fd8db86682b48543d8f89a42793dcf39763e18087a3a6a5138d37bdd97f27d1a04c7fb5eaaf27d935901a0cf638a31974e855f307b43c461c750104f21784610ba0565b6112a56101608601517f02540cd9b058122bd1d78097f3cc6780573b5cd2984e54ab4f99127307f334887f171328630b7b7738c9f59c6dbc537dcdb8139ee0ade45d1d919ad91ce2c64bed84610ba0565b6101c085015192506000805160206117c68339815191528060c087015161032087015109840892506000805160206117c68339815191528060e087015161026087015109840892506000805160206117c68339815191528061010087015161028087015109840892506000805160206117c6833981519152806101208701516102a087015109840892506000805160206117c6833981519152806101408701516102c087015109840892506000805160206117c6833981519152806101608701516102e087015109840892506000805160206117c6833981519152806101808701516103008701510984086000805160206117c68339815191529081030692506113b3836002600184610ba0565b606085015192506113c9836101e0860183610b31565b6000805160206117c683398151915260608601516101808701510992506000805160206117c68339815191526000805160206117e683398151915284099250610c0483610220860183610b31565b60006040516101e0830151815260206101e08401015160208201527f26186a2d65ee4d2f9c9a5b91f86597d35f192cd120caf7e935d8443d1938e23d60408201527f30441fd1b5d3370482c42152a8899027716989a6996c2535bc9f7fee8aaef79e60608201527f1970ea81dd6992adfbc571effb03503adbbb6a857f578403c6c40e22d65b3c0260808201527f054793348f12c0cf5622c340573cb277586319de359ab9389778f689786b1e4860a082015261022083015160c08201526020610220840101517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47817f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47030690508060e0830152507f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26101008201527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6101208201527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6101408201527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa6101608201526020816101808360086107d05a03fa90511692915050565b60405161036081016040526115f484610192565b6115fe8185610208565b61160781610490565b61161183826107ed565b61161b8185610921565b6116258185610c3f565b61162f8185610c70565b61163881611417565b610360820360405280600052505060206000f35b600082601f83011261165c578081fd5b8135602067ffffffffffffffff821115611678576116786117af565b8160051b61168782820161177e565b8381528281019086840183880185018910156116a1578687fd5b8693505b858410156116c35780358352600193909301929184019184016116a5565b50979650505050505050565b600080604083850312156116e1578182fd5b823567ffffffffffffffff808211156116f8578384fd5b818501915085601f83011261170b578384fd5b813560208282111561171f5761171f6117af565b611731601f8301601f1916820161177e565b8281528882848701011115611744578687fd5b828286018383013791820181019590955293850135915080821115611767578283fd5b506117748582860161164c565b9150509250929050565b604051601f8201601f1916810167ffffffffffffffff811182821017156117a7576117a76117af565b604052919050565b634e487b7160e01b600052604160045260246000fdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001006fab49b869ae62001deac878b2667bd31bf3e28e3a2d764aa49b8d9bbdd310a264697066735822122034afae0fbdd2fa7ba7be76a9ffceb9fdd2b44933d5471d6823b3ba262568477964736f6c63430008030033

Deployed ByteCode

0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80631e8e1e1314610030575b600080fd5b61004361003e3660046116cf565b610057565b604051901515815260200160405180910390f35b60006115e0565b600080600184846000805b821561008b575092938183058581029091039350909181830290039081610069565b505050600181111561009c57600080fd5b505060008112156100aa5783015b9392505050565b60405181602084028301815160208301925060005b828410156100f7578185526000805160206117c68339815191528451830991506020850194506020840193506100c6565b61010f6000805160206117c68339815191528361005e565b91506020850394506020840393508592505b82841115610166576000805160206117c68339815191528551830990506000805160206117c683398151915284518309818552601f1995860195909401939150610121565b5090915250505050565b6000805160206117c6833981519152811061018f576000805260206000f35b50565b6103208151146101a6576000805260206000f35b6101b4610260820151610170565b6101c2610280820151610170565b6101d06102a0820151610170565b6101de6102c0820151610170565b6101ec6102e0820151610170565b6101fa610300820151610170565b61018f610320820151610170565b6000806000805160206117c683398151915260c060208501200690508060208501526000805160206117c68339815191526020808601200660408501526000805160206117c6833981519152604060e08501200660008501526000805160206117c683398151915260c06101208501200691508160608501526000805160206117c683398151915282820960a0850152506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990506000805160206117c683398151915281820990508060808401526000805160206117c683398151915280600183030106905080610260840152806102808401526000805160206117c683398151915260e0610260840120068060c08501526000805160206117c683398151915281820991508160e08501526000805160206117c68339815191528183099150816101008501526000805160206117c68339815191528183099150816101208501526000805160206117c68339815191528183099150816101408501526000805160206117c6833981519152818309610160850152505060806101e091909101206000805160206117c6833981519152900661018090910152565b60016000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096102a08301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096102c08301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096102e08301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096103008301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c6833981519152836060860151030106612000096103208301526000805160206117c68339815191526000805160206117e6833981519152820990506000805160206117c6833981519152806000805160206117c683398151915283606086015103010661200009610340830152610677600761028084016100b1565b610260820151600191506000805160206117c6833981519152816102a0850151096102a08401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826102c08601510983096102c08401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826102e08601510983096102e08401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826103008601510983096103008401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c683398151915280826103208601510983096103208401526000805160206117c68339815191526000805160206117e6833981519152830991506000805160206117c68339815191528082610340860151098309610340840152505050565b60006000805160206117c6833981519152806000805160206117c683398151915260208601516102a0860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260408601516102c0860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260608601516102e0860151098303010690506000805160206117c6833981519152806000805160206117c68339815191526080860151610300860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260a0860151610320860151098303010690506000805160206117c6833981519152806000805160206117c683398151915260c086015161034086015109830301069050806101a0830152505050565b60008060006000805160206117c68339815191526101a08601516103208601510892506000805160206117c683398151915260208601516102c08601510991506000805160206117c6833981519152610260850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915260208601516102e08601510990506000805160206117c6833981519152610280850151820890506000805160206117c68339815191526040860151820890506000805160206117c683398151915281830991506000805160206117c683398151915260408601516102a08601510890506000805160206117c683398151915281830991506000805160206117c6833981519152610300850151830991506000805160206117c68339815191526000860151830991506000805160206117c683398151915260008601516102a08701510990506000805160206117c68339815191526000860151820990506000805160206117c68339815191528183089150506000805160206117c6833981519152816000805160206117c6833981519152840103069150506000805160206117c683398151915261028084015182099050806101c0840152505050565b6040518151815260208201516020820152825160408201526020830151606082015260408260808360066107d05a03fa905080610b2c576000805260206000f35b505050565b6000604051835181526020840151602082015284604082015260408160608360076107d05a03fa915081610b69576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa91505080610b9a576000805260206000f35b50505050565b600060405183815284602082015285604082015260408160608360076107d05a03fa915081610bd3576000805260206000f35b825160408201526020830151606082015260408360808360066107d05a03fa91505080610c04576000805260206000f35b5050505050565b600060405183815284602082015285604082015260408360608360076107d05a03fa91505080610c04576000805260206000f35b6101e08201610c5c6101e083018281518152602091820151910152565b610b2c610180840151610220840183610b31565b60008061022084016000805160206117c683398151915260c0860151610260860151099250610ce1837f1b3a7d18f4188ca119d369d1d8be9c235f69bb9ce28f39266e021bc817b2cc707f0ac01dd875295d875318e5463b080e9c5e1f51a342b9faba59c7b7d8533bfdb184610c0b565b6000805160206117c683398151915261028085015184099250610d46837f3028e39b43e930fb20aaff14a85a8843e2db479338d42d1690984a0728836ca47f15b1f4ac25954cd7ffefdd381eed2712796783067e53d79f97220442f6690e2484610ba0565b6000805160206117c683398151915260c0860151610280860151099250610daf837f1b70f37abfc61e9b7d4eb6879d77d24fdf22158e3f7f414cc55eae2d7768f1417f1d81e40939e1600e3b1e0a0673f6ad2f8fd4cd1b9c4e83063e2ca4649b9aff5084610ba0565b6000805160206117c683398151915260c08601516102a0860151099250610e18837f0a77eef902d5c151c65ad12ded8b324255b9bf602ccf59dfb438bb5b626dbbbb7f21b57e6202ee690deadbe4d1c167009146bc5b28812b686d2968b286e1c779c884610ba0565b60c08501519250610e6b837f19ce492a10fd9cc297fade9bf6fc9094bf4a1b5fada98d93ee79774be1173c1e7f1e8c68208b5ec751a2a75fadf90361c33b6820e451ebf87942a9ebdc0bb91a0284610ba0565b6000805160206117c683398151915260a08601516102608601510892506000805160206117c68339815191526040860151840892506000805160206117c683398151915260a086015160020991506000805160206117c6833981519152610280850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915282840992506000805160206117c683398151915260a086015160030991506000805160206117c68339815191526102a0850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915282840992506000805160206117c68339815191526000860151840992506000805160206117c683398151915260c0860151840992506000805160206117c683398151915260008601516102a08701510991506000805160206117c68339815191526000860151830991506000805160206117c683398151915260c0860151830991506000805160206117c683398151915282840892506000805160206117c6833981519152610180860151840892506110148360e0860183610b31565b6000805160206117c68339815191526102c085015160208701510992506000805160206117c6833981519152610260850151840892506000805160206117c68339815191526040860151840892506000805160206117c68339815191526102e085015160208701510991506000805160206117c6833981519152610280850151830891506000805160206117c68339815191526040860151830891506000805160206117c683398151915282840992506000805160206117c68339815191526000860151840992506000805160206117c683398151915260c0860151840992506000805160206117c68339815191526020860151840992506000805160206117c683398151915261030085015184096000805160206117c6833981519152908103069250611184837f129c03adbe966f898444048c9f7e5447371ab4ce76b5f83cb1d25309cca79f6d7f146cef0367944d5e41e44bd661a3591c4af7cee6f0a6f26f60cb29d9605f162984610ba0565b611192610120850182610aeb565b608085015192506111a883610160860183610b31565b6000805160206117c683398151915283840992506111cb836101a0860183610b31565b6111dd60e08601516020860183610b31565b6111f06101008601516060860183610b31565b61120361012086015160a0860183610b31565b6112546101408601517f13729b3fd8db86682b48543d8f89a42793dcf39763e18087a3a6a5138d37bdd97f27d1a04c7fb5eaaf27d935901a0cf638a31974e855f307b43c461c750104f21784610ba0565b6112a56101608601517f02540cd9b058122bd1d78097f3cc6780573b5cd2984e54ab4f99127307f334887f171328630b7b7738c9f59c6dbc537dcdb8139ee0ade45d1d919ad91ce2c64bed84610ba0565b6101c085015192506000805160206117c68339815191528060c087015161032087015109840892506000805160206117c68339815191528060e087015161026087015109840892506000805160206117c68339815191528061010087015161028087015109840892506000805160206117c6833981519152806101208701516102a087015109840892506000805160206117c6833981519152806101408701516102c087015109840892506000805160206117c6833981519152806101608701516102e087015109840892506000805160206117c6833981519152806101808701516103008701510984086000805160206117c68339815191529081030692506113b3836002600184610ba0565b606085015192506113c9836101e0860183610b31565b6000805160206117c683398151915260608601516101808701510992506000805160206117c68339815191526000805160206117e683398151915284099250610c0483610220860183610b31565b60006040516101e0830151815260206101e08401015160208201527f26186a2d65ee4d2f9c9a5b91f86597d35f192cd120caf7e935d8443d1938e23d60408201527f30441fd1b5d3370482c42152a8899027716989a6996c2535bc9f7fee8aaef79e60608201527f1970ea81dd6992adfbc571effb03503adbbb6a857f578403c6c40e22d65b3c0260808201527f054793348f12c0cf5622c340573cb277586319de359ab9389778f689786b1e4860a082015261022083015160c08201526020610220840101517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47817f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47030690508060e0830152507f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26101008201527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6101208201527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b6101408201527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa6101608201526020816101808360086107d05a03fa90511692915050565b60405161036081016040526115f484610192565b6115fe8185610208565b61160781610490565b61161183826107ed565b61161b8185610921565b6116258185610c3f565b61162f8185610c70565b61163881611417565b610360820360405280600052505060206000f35b600082601f83011261165c578081fd5b8135602067ffffffffffffffff821115611678576116786117af565b8160051b61168782820161177e565b8381528281019086840183880185018910156116a1578687fd5b8693505b858410156116c35780358352600193909301929184019184016116a5565b50979650505050505050565b600080604083850312156116e1578182fd5b823567ffffffffffffffff808211156116f8578384fd5b818501915085601f83011261170b578384fd5b813560208282111561171f5761171f6117af565b611731601f8301601f1916820161177e565b8281528882848701011115611744578687fd5b828286018383013791820181019590955293850135915080821115611767578283fd5b506117748582860161164c565b9150509250929050565b604051601f8201601f1916810167ffffffffffffffff811182821017156117a7576117a76117af565b604052919050565b634e487b7160e01b600052604160045260246000fdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001006fab49b869ae62001deac878b2667bd31bf3e28e3a2d764aa49b8d9bbdd310a264697066735822122034afae0fbdd2fa7ba7be76a9ffceb9fdd2b44933d5471d6823b3ba262568477964736f6c63430008030033