Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Verifier
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2025-05-03T04:03:53.567298Z
contracts/Classic/Verifier.sol
// https://tornado.ws Verifier.sol generated by trusted setup ceremony.
/*
* d888888P dP a88888b. dP
* 88 88 d8' `88 88
* 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b.
* 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88
* 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88
* dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP
* ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
*/
// SPDX-License-Identifier: MIT
// 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.7.6;
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
);
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verifyProof","inputs":[{"type":"bytes","name":"proof","internalType":"bytes"},{"type":"uint256[6]","name":"input","internalType":"uint256[6]"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50610e23806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063695ef6f914610030575b600080fd5b610102600480360360e081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184600183028401116401000000008311171561009557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805160c081810190925293969594818101949350915060069083908390808284376000920191909152509194506101169350505050565b604080519115158252519081900360200190f35b6000808380602001905161010081101561012f57600080fd5b50905060005b60088160ff1610156101ba577f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47828260ff166008811061017157fe5b6020020151106101b25760405162461bcd60e51b8152600401808060200182810382526022815260200180610dcc6022913960400191505060405180910390fd5b600101610135565b506101c3610c73565b6040805180820182528351815260208085015181830152908352815160808082018452858401518285019081526060808801519084015282528351808501855290860151815260a08601518184015281830152838201528151808301835260c0850151815260e085015191810191909152908201526000610242610394565b905060006040518060400160405280600081526020016000815250905061027e81836080015160006007811061027457fe5b602002015161085f565b905060005b6006811015610354577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018782600681106102b957fe5b602002015110610310576040805162461bcd60e51b815260206004820152601f60248201527f76657269666965722d6774652d736e61726b2d7363616c61722d6669656c6400604482015290519081900360640190fd5b61034a826103458560800151846001016007811061032a57fe5b60200201518a856006811061033b57fe5b60200201516108ff565b61085f565b9150600101610283565b506103896103658460000151610985565b84602001518460000151856020015185876040015189604001518960600151610a2c565b979650505050505050565b61039c610ca5565b6040805180820182527f2dbfc3ec62a3eee5a3b4b464bcf1f8527bbca12adea0f1f12033cd4f61b0e09181527f19e55bd0b72c126da18665039556776642ff82e2f347f24fcea2475f4db087df6020808301919091529083528151608080820184527f1ae724ab134e5a7c6bd8a116fa5505b259522c0f164a5e8126e3ec7d34465f6e8285019081527e9f1bcdc853f8e3531756bb625b0d1dc014f4ab57c3f79f4f4e2e7ef7e0ead6606080850191909152908352845180860186527f23a8ca5760457e726365b92fd0ceb486665797cd68c35dcffd8e4ae8066691e981527f13ec7182c9fd68331a10f8be0fe885d730de5c7f89aa7d0b7bafaa009bbc9e3e818601528385015285840192909252835180820185527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28186019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed828501528152845180860186527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b81527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa818601528185015285850152835180820185527f2f0c63d0c53b3dfbca27b6b43ae7fbf55a38d78a21470996485b03128accc2088186019081527e556502356e37ed150db2e36531b0f275fd6835c0fc1945922e270b48c48a86828501528152845180860186527f02644c27b5dbd793592a70b735e22c798a5e309fa17a992a7dc2a050e01b298f81527f194776b6a53439d7336f389d2a8f6651e40885f5ca2538b0dc9cb534fb23f7fa818601528185015282860152835180850185527f23df1bc9165e9c1c9b2bc036d8ebdd10e7aeae7e5e8019fde68aec7c818bb23e81527f0b6c92080d37c5fb2ddf30892a33665e5478432ef3f71ac8768ecbbe62c7789281850152818601805191909152845180860186527f1c7b2adf45e046caea000956b2ecb2d8617e710d2a7bb201a95ea276f92307b481527f2b15f07536f45948cf4abe6596637d902ffabb18c8c2f5c151544c294ce4a672818601528151850152845180860186527f1cecfe92882a8c835a47bf01bfa655cf628cbba7f81cf4042179fd13edcd6a3981527f0154bfbb2cb786ca247d4b69183d1751f267bbc7656be8d0f0e7a5a47e2c1101818601528151860152845180860186527f1584616a7423efcc72f69ea84fa0b2bc01433677297f4e8351bebfc15bcd0cda81527f0623755b1488526daa9fecf0e11b110dd6df12c461579d792e1db65af523c8be81860152815190930192909252835180850185527f12fbb5bfca9d61357ba2d641604cf4852e21ef54faa180fe539c18994dc1da5a81527f2f09dd9972a1af5f7bcfccf3d7ab600c9d898ea6d6933150ba0ae228ece17e5f81850152825190910152825180840184527f0adb513796fdf2103022c64151ce05f7c7a6d9200e8d819fa59e654fc4bfe83c81527f2d64f72ef4eddf9ca032058ed2bf691758387e913a77cf99d6a3cfb37c8ba7ee81840152815160a0015282518084019093527f21e7c9bffda74bfd2c4393b6803d775545de6fa89145f4a23476241d9881b66183527f0bbe41e52237ac13eb7b01f3cb999b7394d08734e71b1c3ada62713e17eb560c918301919091525160c0015290565b610867610cec565b61086f610d06565b8351815260208085015181830152835160408301528301516060808301919091526000908360c08460066107d05a03fa90508080156108ad576108af565bfe5b50806108f7576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5859190b59985a5b195960721b604482015290519081900360640190fd5b505092915050565b610907610cec565b61090f610d24565b835181526020808501519082015260408101839052600060608360808460076107d05a03fa90508080156108ad5750806108f7576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5b5d5b0b59985a5b195960721b604482015290519081900360640190fd5b61098d610cec565b815115801561099e57506020820151155b156109bd57506040805180820190915260008082526020820152610a27565b6040518060400160405280836000015181526020017f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478460200151816109ff57fe5b067f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905290505b919050565b60408051608080820183528a825260208083018a90528284018890526060808401879052845192830185528b83528282018a9052828501889052820185905283516018808252610320820190955260009491859190839082016103008036833701905050905060005b6004811015610bec5760068102858260048110610aae57fe5b6020020151518351849083908110610ac257fe5b602002602001018181525050858260048110610ada57fe5b602002015160200151838260010181518110610af257fe5b602002602001018181525050848260048110610b0a57fe5b602002015151518351849060028401908110610b2257fe5b602002602001018181525050848260048110610b3a57fe5b60200201515160016020020151838260030181518110610b5657fe5b602002602001018181525050848260048110610b6e57fe5b602002015160200151600060028110610b8357fe5b6020020151838260040181518110610b9757fe5b602002602001018181525050848260048110610baf57fe5b602002015160200151600160028110610bc457fe5b6020020151838260050181518110610bd857fe5b602090810291909101015250600101610a95565b50610bf5610d42565b6000602082602086026020860160086107d05a03fa90508080156108ad575080610c5e576040805162461bcd60e51b81526020600482015260156024820152741c185a5c9a5b99cb5bdc18dbd9194b59985a5b1959605a1b604482015290519081900360640190fd5b505115159d9c50505050505050505050505050565b6040518060600160405280610c86610cec565b8152602001610c93610d60565b8152602001610ca0610cec565b905290565b6040518060a00160405280610cb8610cec565b8152602001610cc5610d60565b8152602001610cd2610d60565b8152602001610cdf610d60565b8152602001610ca0610d80565b604051806040016040528060008152602001600081525090565b60405180608001604052806004906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060400160405280610d73610dad565b8152602001610ca0610dad565b6040518060e001604052806007905b610d97610cec565b815260200190600190039081610d8f5790505090565b6040518060400160405280600290602082028036833750919291505056fe76657269666965722d70726f6f662d656c656d656e742d6774652d7072696d652d71a26469706673582212201e8d5fa08dca1115d5f49b40f68afdc4edecbc63d464ea55aedda4c788f3adf264736f6c63430007060033
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063695ef6f914610030575b600080fd5b610102600480360360e081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184600183028401116401000000008311171561009557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805160c081810190925293969594818101949350915060069083908390808284376000920191909152509194506101169350505050565b604080519115158252519081900360200190f35b6000808380602001905161010081101561012f57600080fd5b50905060005b60088160ff1610156101ba577f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47828260ff166008811061017157fe5b6020020151106101b25760405162461bcd60e51b8152600401808060200182810382526022815260200180610dcc6022913960400191505060405180910390fd5b600101610135565b506101c3610c73565b6040805180820182528351815260208085015181830152908352815160808082018452858401518285019081526060808801519084015282528351808501855290860151815260a08601518184015281830152838201528151808301835260c0850151815260e085015191810191909152908201526000610242610394565b905060006040518060400160405280600081526020016000815250905061027e81836080015160006007811061027457fe5b602002015161085f565b905060005b6006811015610354577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018782600681106102b957fe5b602002015110610310576040805162461bcd60e51b815260206004820152601f60248201527f76657269666965722d6774652d736e61726b2d7363616c61722d6669656c6400604482015290519081900360640190fd5b61034a826103458560800151846001016007811061032a57fe5b60200201518a856006811061033b57fe5b60200201516108ff565b61085f565b9150600101610283565b506103896103658460000151610985565b84602001518460000151856020015185876040015189604001518960600151610a2c565b979650505050505050565b61039c610ca5565b6040805180820182527f2dbfc3ec62a3eee5a3b4b464bcf1f8527bbca12adea0f1f12033cd4f61b0e09181527f19e55bd0b72c126da18665039556776642ff82e2f347f24fcea2475f4db087df6020808301919091529083528151608080820184527f1ae724ab134e5a7c6bd8a116fa5505b259522c0f164a5e8126e3ec7d34465f6e8285019081527e9f1bcdc853f8e3531756bb625b0d1dc014f4ab57c3f79f4f4e2e7ef7e0ead6606080850191909152908352845180860186527f23a8ca5760457e726365b92fd0ceb486665797cd68c35dcffd8e4ae8066691e981527f13ec7182c9fd68331a10f8be0fe885d730de5c7f89aa7d0b7bafaa009bbc9e3e818601528385015285840192909252835180820185527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28186019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed828501528152845180860186527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b81527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa818601528185015285850152835180820185527f2f0c63d0c53b3dfbca27b6b43ae7fbf55a38d78a21470996485b03128accc2088186019081527e556502356e37ed150db2e36531b0f275fd6835c0fc1945922e270b48c48a86828501528152845180860186527f02644c27b5dbd793592a70b735e22c798a5e309fa17a992a7dc2a050e01b298f81527f194776b6a53439d7336f389d2a8f6651e40885f5ca2538b0dc9cb534fb23f7fa818601528185015282860152835180850185527f23df1bc9165e9c1c9b2bc036d8ebdd10e7aeae7e5e8019fde68aec7c818bb23e81527f0b6c92080d37c5fb2ddf30892a33665e5478432ef3f71ac8768ecbbe62c7789281850152818601805191909152845180860186527f1c7b2adf45e046caea000956b2ecb2d8617e710d2a7bb201a95ea276f92307b481527f2b15f07536f45948cf4abe6596637d902ffabb18c8c2f5c151544c294ce4a672818601528151850152845180860186527f1cecfe92882a8c835a47bf01bfa655cf628cbba7f81cf4042179fd13edcd6a3981527f0154bfbb2cb786ca247d4b69183d1751f267bbc7656be8d0f0e7a5a47e2c1101818601528151860152845180860186527f1584616a7423efcc72f69ea84fa0b2bc01433677297f4e8351bebfc15bcd0cda81527f0623755b1488526daa9fecf0e11b110dd6df12c461579d792e1db65af523c8be81860152815190930192909252835180850185527f12fbb5bfca9d61357ba2d641604cf4852e21ef54faa180fe539c18994dc1da5a81527f2f09dd9972a1af5f7bcfccf3d7ab600c9d898ea6d6933150ba0ae228ece17e5f81850152825190910152825180840184527f0adb513796fdf2103022c64151ce05f7c7a6d9200e8d819fa59e654fc4bfe83c81527f2d64f72ef4eddf9ca032058ed2bf691758387e913a77cf99d6a3cfb37c8ba7ee81840152815160a0015282518084019093527f21e7c9bffda74bfd2c4393b6803d775545de6fa89145f4a23476241d9881b66183527f0bbe41e52237ac13eb7b01f3cb999b7394d08734e71b1c3ada62713e17eb560c918301919091525160c0015290565b610867610cec565b61086f610d06565b8351815260208085015181830152835160408301528301516060808301919091526000908360c08460066107d05a03fa90508080156108ad576108af565bfe5b50806108f7576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5859190b59985a5b195960721b604482015290519081900360640190fd5b505092915050565b610907610cec565b61090f610d24565b835181526020808501519082015260408101839052600060608360808460076107d05a03fa90508080156108ad5750806108f7576040805162461bcd60e51b81526020600482015260126024820152711c185a5c9a5b99cb5b5d5b0b59985a5b195960721b604482015290519081900360640190fd5b61098d610cec565b815115801561099e57506020820151155b156109bd57506040805180820190915260008082526020820152610a27565b6040518060400160405280836000015181526020017f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478460200151816109ff57fe5b067f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905290505b919050565b60408051608080820183528a825260208083018a90528284018890526060808401879052845192830185528b83528282018a9052828501889052820185905283516018808252610320820190955260009491859190839082016103008036833701905050905060005b6004811015610bec5760068102858260048110610aae57fe5b6020020151518351849083908110610ac257fe5b602002602001018181525050858260048110610ada57fe5b602002015160200151838260010181518110610af257fe5b602002602001018181525050848260048110610b0a57fe5b602002015151518351849060028401908110610b2257fe5b602002602001018181525050848260048110610b3a57fe5b60200201515160016020020151838260030181518110610b5657fe5b602002602001018181525050848260048110610b6e57fe5b602002015160200151600060028110610b8357fe5b6020020151838260040181518110610b9757fe5b602002602001018181525050848260048110610baf57fe5b602002015160200151600160028110610bc457fe5b6020020151838260050181518110610bd857fe5b602090810291909101015250600101610a95565b50610bf5610d42565b6000602082602086026020860160086107d05a03fa90508080156108ad575080610c5e576040805162461bcd60e51b81526020600482015260156024820152741c185a5c9a5b99cb5bdc18dbd9194b59985a5b1959605a1b604482015290519081900360640190fd5b505115159d9c50505050505050505050505050565b6040518060600160405280610c86610cec565b8152602001610c93610d60565b8152602001610ca0610cec565b905290565b6040518060a00160405280610cb8610cec565b8152602001610cc5610d60565b8152602001610cd2610d60565b8152602001610cdf610d60565b8152602001610ca0610d80565b604051806040016040528060008152602001600081525090565b60405180608001604052806004906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060400160405280610d73610dad565b8152602001610ca0610dad565b6040518060e001604052806007905b610d97610cec565b815260200190600190039081610d8f5790505090565b6040518060400160405280600290602082028036833750919291505056fe76657269666965722d70726f6f662d656c656d656e742d6774652d7072696d652d71a26469706673582212201e8d5fa08dca1115d5f49b40f68afdc4edecbc63d464ea55aedda4c788f3adf264736f6c63430007060033