Address Details
contract

0x04C2cE746A30875b5E7dDD942adce18095Ff8a8F

Contract Name
Verifier
Creator
0x4c828d–78dc3e at 0x864db2–6dac18
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
4958885
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
Verifier




Optimization enabled
true
Compiler version
v0.5.17+commit.d19bba13




Optimization runs
200
EVM Version
istanbul




Verified at
2022-09-30T07:57:37.864586Z

/home/home/dotfiles/poof-core/contracts/Verifier.sol

// Copyright 2017 Christian Reitwiessner
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// 2019 OKIMS

pragma solidity 0.5.17;

library Pairing {
    uint256 constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;

    struct G1Point {
        uint256 X;
        uint256 Y;
    }

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

    /*
     * @return The negation of p, i.e. p.plus(p.negate()) should be zero.
     */
    function negate(G1Point memory p) internal pure returns (G1Point memory) {
        // The prime q in the base field F_q for G1
        if (p.X == 0 && p.Y == 0) {
            return G1Point(0, 0);
        } else {
            return G1Point(p.X, PRIME_Q - (p.Y % PRIME_Q));
        }
    }

    /*
     * @return r the sum of two points of G1
     */
    function plus(
        G1Point memory p1,
        G1Point memory p2
    ) internal view returns (G1Point memory r) {
        uint256[4] memory input;
        input[0] = p1.X;
        input[1] = p1.Y;
        input[2] = p2.X;
        input[3] = p2.Y;
        bool success;

        // solium-disable-next-line security/no-inline-assembly
        assembly {
            success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)
            // Use "invalid" to make gas estimation work
            switch success case 0 { invalid() }
        }

        require(success, "pairing-add-failed");
    }

    /*
     * @return r the product of a point on G1 and a scalar, i.e.
     *         p == p.scalar_mul(1) and p.plus(p) == p.scalar_mul(2) for all
     *         points p.
     */
    function scalar_mul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) {
        uint256[3] memory input;
        input[0] = p.X;
        input[1] = p.Y;
        input[2] = s;
        bool success;
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
            // Use "invalid" to make gas estimation work
            switch success case 0 { invalid() }
        }
        require(success, "pairing-mul-failed");
    }

    /* @return The result of computing the pairing check
     *         e(p1[0], p2[0]) *  .... * e(p1[n], p2[n]) == 1
     *         For example,
     *         pairing([P1(), P1().negate()], [P2(), P2()]) should return true.
     */
    function pairing(
        G1Point memory a1,
        G2Point memory a2,
        G1Point memory b1,
        G2Point memory b2,
        G1Point memory c1,
        G2Point memory c2,
        G1Point memory d1,
        G2Point memory d2
    ) internal view returns (bool) {
        G1Point[4] memory p1 = [a1, b1, c1, d1];
        G2Point[4] memory p2 = [a2, b2, c2, d2];

        uint256 inputSize = 24;
        uint256[] memory input = new uint256[](inputSize);

        for (uint256 i = 0; i < 4; i++) {
            uint256 j = i * 6;
            input[j + 0] = p1[i].X;
            input[j + 1] = p1[i].Y;
            input[j + 2] = p2[i].X[0];
            input[j + 3] = p2[i].X[1];
            input[j + 4] = p2[i].Y[0];
            input[j + 5] = p2[i].Y[1];
        }

        uint256[1] memory out;
        bool success;

        // solium-disable-next-line security/no-inline-assembly
        assembly {
            success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
            // Use "invalid" to make gas estimation work
            switch success case 0 { invalid() }
        }

        require(success, "pairing-opcode-failed");

        return out[0] != 0;
    }
}

contract Verifier {
    uint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
    uint256 constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    using Pairing for *;

    struct VerifyingKey {
        Pairing.G1Point alfa1;
        Pairing.G2Point beta2;
        Pairing.G2Point gamma2;
        Pairing.G2Point delta2;
        Pairing.G1Point[7] IC;
    }

    struct Proof {
        Pairing.G1Point A;
        Pairing.G2Point B;
        Pairing.G1Point C;
    }

    function verifyingKey() internal pure returns (VerifyingKey memory vk) {
        vk.alfa1 = Pairing.G1Point(uint256(20692898189092739278193869274495556617788530808486270118371701516666252877969), uint256(11713062878292653967971378194351968039596396853904572879488166084231740557279));
        vk.beta2 = Pairing.G2Point([uint256(12168528810181263706895252315640534818222943348193302139358377162645029937006), uint256(281120578337195720357474965979947690431622127986816839208576358024608803542)], [uint256(16129176515713072042442734839012966563817890688785805090011011570989315559913), uint256(9011703453772030375124466642203641636825223906145908770308724549646909480510)]);
        vk.gamma2 = Pairing.G2Point([uint256(11559732032986387107991004021392285783925812861821192530917403151452391805634), uint256(10857046999023057135944570762232829481370756359578518086990519993285655852781)], [uint256(4082367875863433681332203403145435568316851327593401208105741076214120093531), uint256(8495653923123431417604973247489272438418190587263600148770280649306958101930)]);
        vk.delta2 = Pairing.G2Point([uint256(21280594949518992153305586783242820682644996932183186320680800072133486887432), uint256(150879136433974552800030963899771162647715069685890547489132178314736470662)], [uint256(1081836006956609894549771334721413187913047383331561601606260283167615953295), uint256(11434086686358152335540554643130007307617078324975981257823476472104616196090)]);
        vk.IC[0] = Pairing.G1Point(uint256(16225148364316337376768119297456868908427925829817748684139175309620217098814), uint256(5167268689450204162046084442581051565997733233062478317813755636162413164690));
        vk.IC[1] = Pairing.G1Point(uint256(12882377842072682264979317445365303375159828272423495088911985689463022094260), uint256(19488215856665173565526758360510125932214252767275816329232454875804474844786));
        vk.IC[2] = Pairing.G1Point(uint256(13083492661683431044045992285476184182144099829507350352128615182516530014777), uint256(602051281796153692392523702676782023472744522032670801091617246498551238913));
        vk.IC[3] = Pairing.G1Point(uint256(9732465972180335629969421513785602934706096902316483580882842789662669212890), uint256(2776526698606888434074200384264824461688198384989521091253289776235602495678));
        vk.IC[4] = Pairing.G1Point(uint256(8586364274534577154894611080234048648883781955345622578531233113180532234842), uint256(21276134929883121123323359450658320820075698490666870487450985603988214349407));
        vk.IC[5] = Pairing.G1Point(uint256(4910628533171597675018724709631788948355422829499855033965018665300386637884), uint256(20532468890024084510431799098097081600480376127870299142189696620752500664302));
        vk.IC[6] = Pairing.G1Point(uint256(15335858102289947642505450692012116222827233918185150176888641903531542034017), uint256(5311597067667671581646709998171703828965875677637292315055030353779531404812));

    }

    /*
     * @returns Whether the proof is valid given the hardcoded verifying key
     *          above and the public inputs
     */
    function verifyProof(
        bytes memory proof,
        uint256[6] memory input
    ) public view returns (bool) {
        uint256[8] memory p = abi.decode(proof, (uint256[8]));

        // Make sure that each element in the proof is less than the prime q
        for (uint8 i = 0; i < p.length; i++) {
            require(p[i] < PRIME_Q, "verifier-proof-element-gte-prime-q");
        }

        Proof memory _proof;
        _proof.A = Pairing.G1Point(p[0], p[1]);
        _proof.B = Pairing.G2Point([p[2], p[3]], [p[4], p[5]]);
        _proof.C = Pairing.G1Point(p[6], p[7]);

        VerifyingKey memory vk = verifyingKey();

        // Compute the linear combination vk_x
        Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
        vk_x = Pairing.plus(vk_x, vk.IC[0]);

        // Make sure that every input is less than the snark scalar field
        for (uint256 i = 0; i < input.length; i++) {
            require(input[i] < SNARK_SCALAR_FIELD, "verifier-gte-snark-scalar-field");
            vk_x = Pairing.plus(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i]));
        }

        return Pairing.pairing(
            Pairing.negate(_proof.A),
            _proof.B,
            vk.alfa1,
            vk.beta2,
            vk_x,
            vk.gamma2,
            _proof.C,
            vk.delta2
        );
    }
}

        

Contract ABI

[{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verifyProof","inputs":[{"type":"bytes","name":"proof","internalType":"bytes"},{"type":"uint256[6]","name":"input","internalType":"uint256[6]"}],"constant":true}]
              

Contract Creation Code

0x608060405234801561001057600080fd5b50610ec5806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063695ef6f914610030575b600080fd5b610102600480360360e081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184600183028401116401000000008311171561009557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805160c081810190925293969594818101949350915060069083908390808284376000920191909152509194506101169350505050565b604080519115158252519081900360200190f35b6000610120610c9d565b8380602001905161010081101561013657600080fd5b50905060005b60088160ff1610156101c1577f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47828260ff166008811061017857fe5b6020020151106101b95760405162461bcd60e51b8152600401808060200182810382526022815260200180610e6f6022913960400191505060405180910390fd5b60010161013c565b506101ca610cbc565b6040805180820182528351815260208085015181830152908352815160808082018452858401518285019081526060808801519084015282528351808501855290860151815260a08601518184015281830152838201528151808301835260c0850151815260e08501519181019190915290820152610247610cee565b61024f6103a7565b9050610259610d35565b6040518060400160405280600081526020016000815250905061029181836080015160006007811061028757fe5b6020020151610872565b905060005b6006811015610367577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018782600681106102cc57fe5b602002015110610323576040805162461bcd60e51b815260206004820152601f60248201527f76657269666965722d6774652d736e61726b2d7363616c61722d6669656c6400604482015290519081900360640190fd5b61035d826103588560800151846001016007811061033d57fe5b60200201518a856006811061034e57fe5b6020020151610912565b610872565b9150600101610296565b5061039c6103788460000151610998565b84602001518460000151856020015185876040015189604001518960600151610a3f565b979650505050505050565b6103af610cee565b6040805180820182527f2dbfc3ec62a3eee5a3b4b464bcf1f8527bbca12adea0f1f12033cd4f61b0e09181527f19e55bd0b72c126da18665039556776642ff82e2f347f24fcea2475f4db087df6020808301919091529083528151608080820184527f1ae724ab134e5a7c6bd8a116fa5505b259522c0f164a5e8126e3ec7d34465f6e8285019081527e9f1bcdc853f8e3531756bb625b0d1dc014f4ab57c3f79f4f4e2e7ef7e0ead6606080850191909152908352845180860186527f23a8ca5760457e726365b92fd0ceb486665797cd68c35dcffd8e4ae8066691e981527f13ec7182c9fd68331a10f8be0fe885d730de5c7f89aa7d0b7bafaa009bbc9e3e818601528385015285840192909252835180820185527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28186019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed828501528152845180860186527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b81527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa818601528185015285850152835180820185527f2f0c63d0c53b3dfbca27b6b43ae7fbf55a38d78a21470996485b03128accc2088186019081527e556502356e37ed150db2e36531b0f275fd6835c0fc1945922e270b48c48a86828501528152845180860186527f02644c27b5dbd793592a70b735e22c798a5e309fa17a992a7dc2a050e01b298f81527f194776b6a53439d7336f389d2a8f6651e40885f5ca2538b0dc9cb534fb23f7fa818601528185015282860152835180850185527f23df1bc9165e9c1c9b2bc036d8ebdd10e7aeae7e5e8019fde68aec7c818bb23e81527f0b6c92080d37c5fb2ddf30892a33665e5478432ef3f71ac8768ecbbe62c7789281850152818601805191909152845180860186527f1c7b2adf45e046caea000956b2ecb2d8617e710d2a7bb201a95ea276f92307b481527f2b15f07536f45948cf4abe6596637d902ffabb18c8c2f5c151544c294ce4a672818601528151850152845180860186527f1cecfe92882a8c835a47bf01bfa655cf628cbba7f81cf4042179fd13edcd6a3981527f0154bfbb2cb786ca247d4b69183d1751f267bbc7656be8d0f0e7a5a47e2c1101818601528151860152845180860186527f1584616a7423efcc72f69ea84fa0b2bc01433677297f4e8351bebfc15bcd0cda81527f0623755b1488526daa9fecf0e11b110dd6df12c461579d792e1db65af523c8be81860152815190930192909252835180850185527f12fbb5bfca9d61357ba2d641604cf4852e21ef54faa180fe539c18994dc1da5a81527f2f09dd9972a1af5f7bcfccf3d7ab600c9d898ea6d6933150ba0ae228ece17e5f81850152825190910152825180840184527f0adb513796fdf2103022c64151ce05f7c7a6d9200e8d819fa59e654fc4bfe83c81527f2d64f72ef4eddf9ca032058ed2bf691758387e913a77cf99d6a3cfb37c8ba7ee81840152815160a0015282518084019093527f21e7c9bffda74bfd2c4393b6803d775545de6fa89145f4a23476241d9881b66183527f0bbe41e52237ac13eb7b01f3cb999b7394d08734e71b1c3ada62713e17eb560c918301919091525160c0015290565b61087a610d35565b610882610d4f565b8351815260208085015181830152835160408301528301516060808301919091526000908360c08460066107d05a03fa90508080156108c0576108c2565bfe5b508061090a576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5859190b59985a5b195960721b604482015290519081900360640190fd5b505092915050565b61091a610d35565b610922610d6d565b835181526020808501519082015260408101839052600060608360808460076107d05a03fa90508080156108c057508061090a576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5b5d5b0b59985a5b195960721b604482015290519081900360640190fd5b6109a0610d35565b81511580156109b157506020820151155b156109d057506040805180820190915260008082526020820152610a3a565b6040518060400160405280836000015181526020017f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47846020015181610a1257fe5b067f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905290505b919050565b6000610a49610d8b565b60405180608001604052808b8152602001898152602001878152602001858152509050610a74610db8565b50604080516080810182528a81526020810189905280820187905260608082018690528251601880825261032082019094529192918281602001602082028038833901905050905060005b6004811015610c165760068102858260048110610ad857fe5b6020020151518351849083908110610aec57fe5b602002602001018181525050858260048110610b0457fe5b602002015160200151838260010181518110610b1c57fe5b602002602001018181525050848260048110610b3457fe5b602002015151518351849060028401908110610b4c57fe5b602002602001018181525050848260048110610b6457fe5b60200201515160016020020151838260030181518110610b8057fe5b602002602001018181525050848260048110610b9857fe5b602002015160200151600060028110610bad57fe5b6020020151838260040181518110610bc157fe5b602002602001018181525050848260048110610bd957fe5b602002015160200151600160028110610bee57fe5b6020020151838260050181518110610c0257fe5b602090810291909101015250600101610abf565b50610c1f610de5565b6000602082602086026020860160086107d05a03fa90508080156108c0575080610c88576040805162461bcd60e51b81526020600482015260156024820152741c185a5c9a5b99cb5bdc18dbd9194b59985a5b1959605a1b604482015290519081900360640190fd5b505115159d9c50505050505050505050505050565b6040518061010001604052806008906020820280388339509192915050565b6040518060600160405280610ccf610d35565b8152602001610cdc610e03565b8152602001610ce9610d35565b905290565b6040518060a00160405280610d01610d35565b8152602001610d0e610e03565b8152602001610d1b610e03565b8152602001610d28610e03565b8152602001610ce9610e23565b604051806040016040528060008152602001600081525090565b60405180608001604052806004906020820280388339509192915050565b60405180606001604052806003906020820280388339509192915050565b60405180608001604052806004905b610da2610d35565b815260200190600190039081610d9a5790505090565b60405180608001604052806004905b610dcf610e03565b815260200190600190039081610dc75790505090565b60405180602001604052806001906020820280388339509192915050565b6040518060400160405280610e16610e50565b8152602001610ce9610e50565b6040518060e001604052806007905b610e3a610d35565b815260200190600190039081610e325790505090565b6040518060400160405280600290602082028038833950919291505056fe76657269666965722d70726f6f662d656c656d656e742d6774652d7072696d652d71a265627a7a72315820c377a07590227f86d4e0b510e5392558a386c1c48993120254f45b4dc65a0f7564736f6c63430005110032

Deployed ByteCode

0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063695ef6f914610030575b600080fd5b610102600480360360e081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184600183028401116401000000008311171561009557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805160c081810190925293969594818101949350915060069083908390808284376000920191909152509194506101169350505050565b604080519115158252519081900360200190f35b6000610120610c9d565b8380602001905161010081101561013657600080fd5b50905060005b60088160ff1610156101c1577f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47828260ff166008811061017857fe5b6020020151106101b95760405162461bcd60e51b8152600401808060200182810382526022815260200180610e6f6022913960400191505060405180910390fd5b60010161013c565b506101ca610cbc565b6040805180820182528351815260208085015181830152908352815160808082018452858401518285019081526060808801519084015282528351808501855290860151815260a08601518184015281830152838201528151808301835260c0850151815260e08501519181019190915290820152610247610cee565b61024f6103a7565b9050610259610d35565b6040518060400160405280600081526020016000815250905061029181836080015160006007811061028757fe5b6020020151610872565b905060005b6006811015610367577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018782600681106102cc57fe5b602002015110610323576040805162461bcd60e51b815260206004820152601f60248201527f76657269666965722d6774652d736e61726b2d7363616c61722d6669656c6400604482015290519081900360640190fd5b61035d826103588560800151846001016007811061033d57fe5b60200201518a856006811061034e57fe5b6020020151610912565b610872565b9150600101610296565b5061039c6103788460000151610998565b84602001518460000151856020015185876040015189604001518960600151610a3f565b979650505050505050565b6103af610cee565b6040805180820182527f2dbfc3ec62a3eee5a3b4b464bcf1f8527bbca12adea0f1f12033cd4f61b0e09181527f19e55bd0b72c126da18665039556776642ff82e2f347f24fcea2475f4db087df6020808301919091529083528151608080820184527f1ae724ab134e5a7c6bd8a116fa5505b259522c0f164a5e8126e3ec7d34465f6e8285019081527e9f1bcdc853f8e3531756bb625b0d1dc014f4ab57c3f79f4f4e2e7ef7e0ead6606080850191909152908352845180860186527f23a8ca5760457e726365b92fd0ceb486665797cd68c35dcffd8e4ae8066691e981527f13ec7182c9fd68331a10f8be0fe885d730de5c7f89aa7d0b7bafaa009bbc9e3e818601528385015285840192909252835180820185527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28186019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed828501528152845180860186527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b81527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa818601528185015285850152835180820185527f2f0c63d0c53b3dfbca27b6b43ae7fbf55a38d78a21470996485b03128accc2088186019081527e556502356e37ed150db2e36531b0f275fd6835c0fc1945922e270b48c48a86828501528152845180860186527f02644c27b5dbd793592a70b735e22c798a5e309fa17a992a7dc2a050e01b298f81527f194776b6a53439d7336f389d2a8f6651e40885f5ca2538b0dc9cb534fb23f7fa818601528185015282860152835180850185527f23df1bc9165e9c1c9b2bc036d8ebdd10e7aeae7e5e8019fde68aec7c818bb23e81527f0b6c92080d37c5fb2ddf30892a33665e5478432ef3f71ac8768ecbbe62c7789281850152818601805191909152845180860186527f1c7b2adf45e046caea000956b2ecb2d8617e710d2a7bb201a95ea276f92307b481527f2b15f07536f45948cf4abe6596637d902ffabb18c8c2f5c151544c294ce4a672818601528151850152845180860186527f1cecfe92882a8c835a47bf01bfa655cf628cbba7f81cf4042179fd13edcd6a3981527f0154bfbb2cb786ca247d4b69183d1751f267bbc7656be8d0f0e7a5a47e2c1101818601528151860152845180860186527f1584616a7423efcc72f69ea84fa0b2bc01433677297f4e8351bebfc15bcd0cda81527f0623755b1488526daa9fecf0e11b110dd6df12c461579d792e1db65af523c8be81860152815190930192909252835180850185527f12fbb5bfca9d61357ba2d641604cf4852e21ef54faa180fe539c18994dc1da5a81527f2f09dd9972a1af5f7bcfccf3d7ab600c9d898ea6d6933150ba0ae228ece17e5f81850152825190910152825180840184527f0adb513796fdf2103022c64151ce05f7c7a6d9200e8d819fa59e654fc4bfe83c81527f2d64f72ef4eddf9ca032058ed2bf691758387e913a77cf99d6a3cfb37c8ba7ee81840152815160a0015282518084019093527f21e7c9bffda74bfd2c4393b6803d775545de6fa89145f4a23476241d9881b66183527f0bbe41e52237ac13eb7b01f3cb999b7394d08734e71b1c3ada62713e17eb560c918301919091525160c0015290565b61087a610d35565b610882610d4f565b8351815260208085015181830152835160408301528301516060808301919091526000908360c08460066107d05a03fa90508080156108c0576108c2565bfe5b508061090a576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5859190b59985a5b195960721b604482015290519081900360640190fd5b505092915050565b61091a610d35565b610922610d6d565b835181526020808501519082015260408101839052600060608360808460076107d05a03fa90508080156108c057508061090a576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5b5d5b0b59985a5b195960721b604482015290519081900360640190fd5b6109a0610d35565b81511580156109b157506020820151155b156109d057506040805180820190915260008082526020820152610a3a565b6040518060400160405280836000015181526020017f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47846020015181610a1257fe5b067f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905290505b919050565b6000610a49610d8b565b60405180608001604052808b8152602001898152602001878152602001858152509050610a74610db8565b50604080516080810182528a81526020810189905280820187905260608082018690528251601880825261032082019094529192918281602001602082028038833901905050905060005b6004811015610c165760068102858260048110610ad857fe5b6020020151518351849083908110610aec57fe5b602002602001018181525050858260048110610b0457fe5b602002015160200151838260010181518110610b1c57fe5b602002602001018181525050848260048110610b3457fe5b602002015151518351849060028401908110610b4c57fe5b602002602001018181525050848260048110610b6457fe5b60200201515160016020020151838260030181518110610b8057fe5b602002602001018181525050848260048110610b9857fe5b602002015160200151600060028110610bad57fe5b6020020151838260040181518110610bc157fe5b602002602001018181525050848260048110610bd957fe5b602002015160200151600160028110610bee57fe5b6020020151838260050181518110610c0257fe5b602090810291909101015250600101610abf565b50610c1f610de5565b6000602082602086026020860160086107d05a03fa90508080156108c0575080610c88576040805162461bcd60e51b81526020600482015260156024820152741c185a5c9a5b99cb5bdc18dbd9194b59985a5b1959605a1b604482015290519081900360640190fd5b505115159d9c50505050505050505050505050565b6040518061010001604052806008906020820280388339509192915050565b6040518060600160405280610ccf610d35565b8152602001610cdc610e03565b8152602001610ce9610d35565b905290565b6040518060a00160405280610d01610d35565b8152602001610d0e610e03565b8152602001610d1b610e03565b8152602001610d28610e03565b8152602001610ce9610e23565b604051806040016040528060008152602001600081525090565b60405180608001604052806004906020820280388339509192915050565b60405180606001604052806003906020820280388339509192915050565b60405180608001604052806004905b610da2610d35565b815260200190600190039081610d9a5790505090565b60405180608001604052806004905b610dcf610e03565b815260200190600190039081610dc75790505090565b60405180602001604052806001906020820280388339509192915050565b6040518060400160405280610e16610e50565b8152602001610ce9610e50565b6040518060e001604052806007905b610e3a610d35565b815260200190600190039081610e325790505090565b6040518060400160405280600290602082028038833950919291505056fe76657269666965722d70726f6f662d656c656d656e742d6774652d7072696d652d71a265627a7a72315820c377a07590227f86d4e0b510e5392558a386c1c48993120254f45b4dc65a0f7564736f6c63430005110032