Contract 0x8cc4c8529c0D8bb9B9FA197530d656cCBcB88DeB

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x5212a2106d184c30dc30bf8c047617b25d94a13b50a2a5252fd515cbca033ced0xc3b6dcdc120984062021-10-26 5:19:451 day 12 hrs ago0xa9311b623c2b72f77adbbd091c70f60d8cc2d2fb IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.01213685
0xaabdf4a576a4575e03b84143ff75076c001fc9712663e3b950baa93cefb2a35c0x042ed32a120983002021-10-26 5:14:271 day 12 hrs ago0xa9311b623c2b72f77adbbd091c70f60d8cc2d2fb IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00114482
0x8fbf525916f5be75d4a42707efc1f34a61c7adecaef806c02c95f89457c4d7da0x9b0d85d3120982522021-10-26 5:12:031 day 12 hrs ago0xa9311b623c2b72f77adbbd091c70f60d8cc2d2fb IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068472
0x659ad4dc8c665dc5b004556da1bdabf6351065dd52eeb657a09c452f6a049c0a0x9b0d85d3104852412021-08-30 17:46:4457 days 23 hrs ago0x970a50034271dbc906a163d9e81f2a5c7e9489f0 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x75d9c56a62914f8cfa0ab1cd02fca8e918c55ca23020b24d0a77413518ff81930x9b0d85d3100634052021-08-15 23:18:5672 days 18 hrs ago0x043420587faa9a292e0b689bd7d096f9570a28fc IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x5142abf1eea22f9f446b0645284c56a2aeaf2087de0854a8bf9db290c5c4edb10x9b0d85d392337502021-07-17 10:53:37102 days 6 hrs ago0x39f6befb0a0eda493507713061ee5983f55a49d6 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x37c49c0febc20b0e3bf160f23cb0264ed7c1ab8a3b6fd25d5af4aa379e6b89810x9b0d85d392042252021-07-16 10:17:15103 days 7 hrs ago0x3f0500b79c099dfe2638d0faf1c03f56b90d12d1 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0xa9d6a11aa3aaa7974f52a2f35385965051396bed4e6b0f49de69c9c52e363cf80x9b0d85d391977572021-07-16 4:53:20103 days 12 hrs ago0x65b605c2c4799688afb4b60cf2cf358a550d2e17 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068472
0x9ac8dbc8ad57f3c2722852f80655b9f9d0bffa008c2c02e2647ad37723fb4f7a0xc3b6dcdc91880922021-07-15 20:50:05103 days 20 hrs ago0x4e76c59047920b20f3fd2394b7e7142a0dd39b90 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.012455345
0xd2fa26274c8230fefd457ff0aca80c8f8f1f6b527f0a2ebc35d4e556aa87e7af0x042ed32a91875262021-07-15 20:21:47103 days 21 hrs ago0x4e76c59047920b20f3fd2394b7e7142a0dd39b90 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00114476
0xaebbc45251cb823cd27a3e68667b817c56ffd22fafb01267d4eda328baea16060x9b0d85d391874862021-07-15 20:19:47103 days 21 hrs ago0x4e76c59047920b20f3fd2394b7e7142a0dd39b90 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068466
0x4f1f434d9720831f9f648bec98e2f6f3055008abfd0ac72fbd7c5b00bffc9a890x9b0d85d391125232021-07-13 5:50:12106 days 11 hrs ago0xf25b560b143f7a5a5b6bd0edf8b68ac7fe2ac753 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x56b8e8924cb9095ef3111d584115aca466b516eeb3a63186f41d8c9f7df4482e0x9b0d85d390270142021-07-10 6:34:22109 days 11 hrs ago0x46b8566e6a854fe7497b6650f8f8e549c87226f4 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0xd4722f34695dc1fb93f0e180f35d66828236b0619d1316ae78feffbda32d51570x9b0d85d390233482021-07-10 3:31:04109 days 14 hrs ago0x97b4bf4945c48aecf7c8b1bda60bf4f8925fc0bc IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0xb26e10073609ddfa28f4680f788901bfcfb5712b2875d18557a8f41fb98bdc680xc3b6dcdc89243142021-07-06 16:56:59113 days 39 mins ago0x984f8e973cae0188d7122da946863b5c444264fe IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.012140585
0x534370c1c8d18fd05bf2c476c609c8c3d9920d7d749947d7442d65c1993b93c70x042ed32a89242642021-07-06 16:54:29113 days 42 mins ago0x984f8e973cae0188d7122da946863b5c444264fe IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00114482
0x7df63312f8595e8f1cf26e8d4e1774215d0658e72f2872e904620f4f0148a2830x9b0d85d389193512021-07-06 12:47:17113 days 4 hrs ago0x984f8e973cae0188d7122da946863b5c444264fe IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x76031f134fec4169427f9ce4bd9fb4ce9897b405d5e09b77c7b5b366305239620x9b0d85d388779902021-07-05 1:58:15114 days 15 hrs ago0xbc311f59c4f50b8ba73a03403ce5db82f767cbf7 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068472
0x6fa1f1f1afd1e6c4ae0720e883855c8121a07aaac42aa6063e76e2dd48e703320x9b0d85d388556662021-07-04 7:16:43115 days 10 hrs ago0xbc311f59c4f50b8ba73a03403ce5db82f767cbf7 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068472
0xbbeda3e387a5adf34376066aeef097ca5e5b9e10622838bad2b22811d5f642020x9b0d85d387786632021-07-01 14:28:26118 days 3 hrs ago0x7640826546ffd3886870128eb934967db5b1d5aa IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068472
0x210e82e0cd7d75babe91c6edc5832f75cdc5d7b0d3997d933fcefba03ad691c60x9b0d85d387576452021-06-30 20:48:09118 days 20 hrs ago0xb3662615f52e788ca26c7d843e0ffc8cf19339da IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x7583860aa14a987f8d8b30d82ae221794aaefaf8766f0813299cb79ca31dbfc10x9b0d85d387396132021-06-30 5:36:00119 days 12 hrs ago0x173d244d4ca59531acf7428f56c0227bfa03e86c IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x3ed1e9d0a1298916860704e7271b4a3977f07896355fdd19ada7961c030e7bb60x9b0d85d387306342021-06-29 22:03:27119 days 19 hrs ago0xb99a280e998bfbb24bcda83dc517867e5251008b IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x1e5fab592328eabbcf1e53ec4ea6082017f3f38006be77a9f87bc984273ea74c0x9b0d85d387250722021-06-29 17:23:53120 days 12 mins ago0x08601f1d2f73c68a18dfde1f9c32142098c87265 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
0x0d3bc4be36bef54b502ab641fd28b89997c44c67c90c32e8c2868aed21d852c70x9b0d85d386945792021-06-28 15:47:21121 days 1 hr ago0xf378cbb376beccf2d5d433955cd03b0e8bd81e98 IN  0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0 BNB0.00068478
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x000fb0bb895ed193d36561d08b1ddd23794418029c09e9990c4979f971742f6b56370862021-03-13 6:22:04228 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xa0d802ef2c5dd652fa3f14e950887317e35c87a20.04494796 BNB
0x000fb0bb895ed193d36561d08b1ddd23794418029c09e9990c4979f971742f6b56370862021-03-13 6:22:04228 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00975204 BNB
0xa139ab1ab91fe740c9901f436d93949edfd2bf71c1a83d8c420cb0c9eb0c7ec755671442021-03-10 19:55:17230 days 21 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xbcb4c8386c097589e7825aaeb9e7c6295835f1d60.04476537 BNB
0xa139ab1ab91fe740c9901f436d93949edfd2bf71c1a83d8c420cb0c9eb0c7ec755671442021-03-10 19:55:17230 days 21 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00993463 BNB
0x5a5454c4b7927d25599c3b86e955dc5ebb9cc758e76b53a7b53ffb704c744bc455255052021-03-09 9:09:28232 days 8 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0x301a4125ae628984fa2b419ee8fb527a4873312e0.04490473 BNB
0x5a5454c4b7927d25599c3b86e955dc5ebb9cc758e76b53a7b53ffb704c744bc455255052021-03-09 9:09:28232 days 8 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00979527 BNB
0xff2f61f0256d4a59fce4c4c014570940834d0dd4bab9f803b8f9d165eab9a1e854133332021-03-05 11:37:55236 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0xff2f61f0256d4a59fce4c4c014570940834d0dd4bab9f803b8f9d165eab9a1e854133332021-03-05 11:37:55236 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0xff2f61f0256d4a59fce4c4c014570940834d0dd4bab9f803b8f9d165eab9a1e854133332021-03-05 11:37:55236 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb 0xd3a56c7fd5493268d299a4111a1b493c95b0b5690 BNB
0x55562e71b2d0e425b0612aa25343ba78baaade499a0d7ac9baf37c10c988be0b54133012021-03-05 11:36:19236 days 6 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0xc0b6b327d45f3c6aa999d096ac7b731f8f36291cf6460396a3e968902624f1cc53775252021-03-04 5:47:16237 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0x288e1a5d8b1933fc424001426b2a2507bd2031850.04498641 BNB
0xc0b6b327d45f3c6aa999d096ac7b731f8f36291cf6460396a3e968902624f1cc53775252021-03-04 5:47:16237 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00971359 BNB
0xc0b6b327d45f3c6aa999d096ac7b731f8f36291cf6460396a3e968902624f1cc53775252021-03-04 5:47:16237 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb 0x076010bfc6377b24d10545e69840c9a6b79d64710 BNB
0x49070c36322249e31c955ac9f41629682fcec9e90bfd025717be5b4bb5eb717b53774962021-03-04 5:45:49237 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xcb5dbcfc885a096db2cb1e4029faa5359f5223b50.04490454 BNB
0x49070c36322249e31c955ac9f41629682fcec9e90bfd025717be5b4bb5eb717b53774962021-03-04 5:45:49237 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00979546 BNB
0x49070c36322249e31c955ac9f41629682fcec9e90bfd025717be5b4bb5eb717b53774962021-03-04 5:45:49237 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb 0x076010bfc6377b24d10545e69840c9a6b79d64710 BNB
0xc4dae1904cd263f2c6330dcc5e9045e61ad0ea4c8c543b3628c7db959cc853d253773152021-03-04 5:36:46237 days 11 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0xb1214d11e64870709d0df34bd359e1cca24d04b67775c21ba36d65f1beeda6c053771342021-03-04 5:27:43237 days 12 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0x96c6efb1f2ae38bcc9c922733ce8195c33d05716951c3f30e03444b8735934ca53590382021-03-03 14:22:19238 days 3 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0x7945f36f55c2b12202d11962d37ab2f41baf45cd282c43cd655af9f9ca174f9153575532021-03-03 12:44:46238 days 4 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0x5b5d49e0f9eb529d3112ac60f1a03b023253395e45fc3876308e8ccbe44e375453573602021-03-03 12:29:24238 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0x5b5d49e0f9eb529d3112ac60f1a03b023253395e45fc3876308e8ccbe44e375453573602021-03-03 12:29:24238 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb PancakeSwap: CAKE Token0 BNB
0x5b5d49e0f9eb529d3112ac60f1a03b023253395e45fc3876308e8ccbe44e375453573602021-03-03 12:29:24238 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb 0xd3a56c7fd5493268d299a4111a1b493c95b0b5690 BNB
0x833b6fe575bb182a5b54dc80465f8b61b41831305d907d70f1c352f3771ce3fa53573442021-03-03 12:28:19238 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0x301a4125ae628984fa2b419ee8fb527a4873312e0.0447654 BNB
0x833b6fe575bb182a5b54dc80465f8b61b41831305d907d70f1c352f3771ce3fa53573442021-03-03 12:28:19238 days 5 hrs ago 0x8cc4c8529c0d8bb9b9fa197530d656ccbcb88deb0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.0099346 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xe557c77Ed24df7cDF21ED55a8C56Ea36CeBD5BD2

Contract Name:
SuterERC20

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity Multiple files format)

File 1 of 10: SuterERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./ERC20.sol";
import "./Utils.sol";
import "./SuterBase.sol";


contract SuterERC20 is SuterBase {

    ERC20 token;

    //constructor(address payable _suterAgency, Utils.G1Point memory _suterAgencyPublicKey, address _token, address _transfer, address _burn, uint256 _epochBase, uint256 _epochLength, uint256 _unit) SuterBase(_suterAgency, _suterAgencyPublicKey, _transfer, _burn, _epochBase, _epochLength, _unit) public {
        //token = ERC20(_token);
    //}

    constructor(address _token, address _transfer, address _burn, uint256 _unit) SuterBase(_transfer, _burn, _unit) public {
        token = ERC20(_token);
    }

    function fund(Utils.G1Point memory y, uint256 unitAmount, bytes memory encGuess) public {
        fundBase(y, unitAmount, encGuess);

        uint256 nativeAmount = toNativeAmount(unitAmount);

        // In order for the following to succeed, `msg.sender` have to first approve `this` to spend the nativeAmount.
        require(token.transferFrom(msg.sender, address(this), nativeAmount), "Native 'transferFrom' failed.");
    }

    function burn(Utils.G1Point memory y, uint256 unitAmount, Utils.G1Point memory u, bytes memory proof, bytes memory encGuess) public {
        uint256 nativeAmount = toNativeAmount(unitAmount);
        uint256 fee = nativeAmount * BURN_FEE_MULTIPLIER / BURN_FEE_DIVIDEND; 

        burnBase(y, unitAmount, u, proof, encGuess);

        if (fee > 0) {
            require(token.transfer(suterAgency, fee), "Fail to charge fee.");
            totalBurnFee = totalBurnFee + fee;
        }
        require(token.transfer(msg.sender, nativeAmount - fee), "Fail to transfer tokens.");
    }
}



File 2 of 10: BurnVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./Utils.sol";
import "./InnerProductVerifier.sol";

contract BurnVerifier {
    using Utils for uint256;
    using Utils for Utils.G1Point;

    InnerProductVerifier ip;

    struct BurnStatement {
        Utils.G1Point CLn;
        Utils.G1Point CRn;
        Utils.G1Point y;
        uint256 epoch; // or uint8?
        address sender;
        Utils.G1Point u;
    }

    struct BurnProof {
        Utils.G1Point BA;
        Utils.G1Point BS;

        Utils.G1Point[2] tCommits;
        uint256 tHat;
        uint256 mu;

        uint256 c;
        uint256 s_sk;
        uint256 s_b;
        uint256 s_tau;

        InnerProductVerifier.InnerProductProof ipProof;
    }

    constructor(address _ip) public {
        ip = InnerProductVerifier(_ip);
    }

    function verifyBurn(Utils.G1Point memory CLn, Utils.G1Point memory CRn, Utils.G1Point memory y, uint256 epoch, Utils.G1Point memory u, address sender, bytes memory proof) public view returns (bool) {
        BurnStatement memory statement; // WARNING: if this is called directly in the console,
        // and your strings are less than 64 characters, they will be padded on the right, not the left. should hopefully not be an issue,
        // as this will typically be called simply by the other contract. still though, beware
        statement.CLn = CLn;
        statement.CRn = CRn;
        statement.y = y;
        statement.epoch = epoch;
        statement.u = u;
        statement.sender = sender;
        BurnProof memory burnProof = unserialize(proof);
        return verify(statement, burnProof);
    }

    struct BurnAuxiliaries {
        uint256 y;
        uint256[32] ys;
        uint256 z;
        uint256[1] zs; // silly. just to match zether.
        uint256 zSum;
        uint256[32] twoTimesZSquared;
        uint256 x;
        uint256 t;
        uint256 k;
        Utils.G1Point tEval;
    }

    struct SigmaAuxiliaries {
        uint256 c;
        Utils.G1Point A_y;
        Utils.G1Point A_b;
        Utils.G1Point A_t;
        Utils.G1Point gEpoch;
        Utils.G1Point A_u;
    }

    struct IPAuxiliaries {
        Utils.G1Point P;
        Utils.G1Point u_x;
        Utils.G1Point[] hPrimes;
        Utils.G1Point hPrimeSum;
        uint256 o;
    }

    function gSum() internal pure returns (Utils.G1Point memory) {
        return Utils.G1Point(0x2257118d30fe5064dda298b2fac15cf96fd51f0e7e3df342d0aed40b8d7bb151, 0x0d4250e7509c99370e6b15ebfe4f1aa5e65a691133357901aa4b0641f96c80a8);
    }

    function verify(BurnStatement memory statement, BurnProof memory proof) internal view returns (bool) {
        uint256 statementHash = uint256(keccak256(abi.encode(statement.CLn, statement.CRn, statement.y, statement.epoch, statement.sender))).gMod(); // stacktoodeep?

        BurnAuxiliaries memory burnAuxiliaries;
        burnAuxiliaries.y = uint256(keccak256(abi.encode(statementHash, proof.BA, proof.BS))).gMod();
        burnAuxiliaries.ys[0] = 1;
        burnAuxiliaries.k = 1;
        for (uint256 i = 1; i < 32; i++) {
            burnAuxiliaries.ys[i] = burnAuxiliaries.ys[i - 1].gMul(burnAuxiliaries.y);
            burnAuxiliaries.k = burnAuxiliaries.k.gAdd(burnAuxiliaries.ys[i]);
        }
        burnAuxiliaries.z = uint256(keccak256(abi.encode(burnAuxiliaries.y))).gMod();
        burnAuxiliaries.zs = [burnAuxiliaries.z.gExp(2)];
        burnAuxiliaries.zSum = burnAuxiliaries.zs[0].gMul(burnAuxiliaries.z); // trivial sum
        burnAuxiliaries.k = burnAuxiliaries.k.gMul(burnAuxiliaries.z.gSub(burnAuxiliaries.zs[0])).gSub(burnAuxiliaries.zSum.gMul(2 ** 32).gSub(burnAuxiliaries.zSum));
        burnAuxiliaries.t = proof.tHat.gSub(burnAuxiliaries.k);
        for (uint256 i = 0; i < 32; i++) {
            burnAuxiliaries.twoTimesZSquared[i] = burnAuxiliaries.zs[0].gMul(2 ** i);
        }

        burnAuxiliaries.x = uint256(keccak256(abi.encode(burnAuxiliaries.z, proof.tCommits))).gMod();
        burnAuxiliaries.tEval = proof.tCommits[0].pMul(burnAuxiliaries.x).pAdd(proof.tCommits[1].pMul(burnAuxiliaries.x.gMul(burnAuxiliaries.x))); // replace with "commit"?

        SigmaAuxiliaries memory sigmaAuxiliaries;
        sigmaAuxiliaries.A_y = Utils.g().pMul(proof.s_sk).pAdd(statement.y.pMul(proof.c.gNeg()));
        sigmaAuxiliaries.A_b = Utils.g().pMul(proof.s_b).pAdd(statement.CRn.pMul(proof.s_sk).pAdd(statement.CLn.pMul(proof.c.gNeg())).pMul(burnAuxiliaries.zs[0]));
        sigmaAuxiliaries.A_t = Utils.g().pMul(burnAuxiliaries.t).pAdd(burnAuxiliaries.tEval.pNeg()).pMul(proof.c).pAdd(Utils.h().pMul(proof.s_tau)).pAdd(Utils.g().pMul(proof.s_b.gNeg()));
        sigmaAuxiliaries.gEpoch = Utils.mapInto("Suter", statement.epoch);
        sigmaAuxiliaries.A_u = sigmaAuxiliaries.gEpoch.pMul(proof.s_sk).pAdd(statement.u.pMul(proof.c.gNeg()));

        sigmaAuxiliaries.c = uint256(keccak256(abi.encode(burnAuxiliaries.x, sigmaAuxiliaries.A_y, sigmaAuxiliaries.A_b, sigmaAuxiliaries.A_t, sigmaAuxiliaries.A_u))).gMod();
        require(sigmaAuxiliaries.c == proof.c, string(abi.encodePacked("Sigma protocol challenge equality failure. Epoch: ", Utils.uint2str(statement.epoch))));

        IPAuxiliaries memory ipAuxiliaries;
        ipAuxiliaries.o = uint256(keccak256(abi.encode(sigmaAuxiliaries.c))).gMod();
        ipAuxiliaries.u_x = Utils.g().pMul(ipAuxiliaries.o);
        ipAuxiliaries.hPrimes = new Utils.G1Point[](32);
        for (uint256 i = 0; i < 32; i++) {
            ipAuxiliaries.hPrimes[i] = ip.hs(i).pMul(burnAuxiliaries.ys[i].gInv());
            ipAuxiliaries.hPrimeSum = ipAuxiliaries.hPrimeSum.pAdd(ipAuxiliaries.hPrimes[i].pMul(burnAuxiliaries.ys[i].gMul(burnAuxiliaries.z).gAdd(burnAuxiliaries.twoTimesZSquared[i])));
        }
        ipAuxiliaries.P = proof.BA.pAdd(proof.BS.pMul(burnAuxiliaries.x)).pAdd(gSum().pMul(burnAuxiliaries.z.gNeg())).pAdd(ipAuxiliaries.hPrimeSum);
        ipAuxiliaries.P = ipAuxiliaries.P.pAdd(Utils.h().pMul(proof.mu.gNeg()));
        ipAuxiliaries.P = ipAuxiliaries.P.pAdd(ipAuxiliaries.u_x.pMul(proof.tHat));
        require(ip.verifyInnerProduct(ipAuxiliaries.hPrimes, ipAuxiliaries.u_x, ipAuxiliaries.P, proof.ipProof, ipAuxiliaries.o), "Inner product proof verification failed.");

        return true;
    }

    function unserialize(bytes memory arr) internal pure returns (BurnProof memory proof) {
        proof.BA = Utils.G1Point(Utils.slice(arr, 0), Utils.slice(arr, 32));
        proof.BS = Utils.G1Point(Utils.slice(arr, 64), Utils.slice(arr, 96));

        proof.tCommits = [Utils.G1Point(Utils.slice(arr, 128), Utils.slice(arr, 160)), Utils.G1Point(Utils.slice(arr, 192), Utils.slice(arr, 224))];
        proof.tHat = uint256(Utils.slice(arr, 256));
        proof.mu = uint256(Utils.slice(arr, 288));

        proof.c = uint256(Utils.slice(arr, 320));
        proof.s_sk = uint256(Utils.slice(arr, 352));
        proof.s_b = uint256(Utils.slice(arr, 384));
        proof.s_tau = uint256(Utils.slice(arr, 416));

        InnerProductVerifier.InnerProductProof memory ipProof;
        ipProof.ls = new Utils.G1Point[](5);
        ipProof.rs = new Utils.G1Point[](5);
        for (uint256 i = 0; i < 5; i++) { // 2^5 = 32.
            ipProof.ls[i] = Utils.G1Point(Utils.slice(arr, 448 + i * 64), Utils.slice(arr, 480 + i * 64));
            ipProof.rs[i] = Utils.G1Point(Utils.slice(arr, 448 + (5 + i) * 64), Utils.slice(arr, 480 + (5 + i) * 64));
        }
        ipProof.a = uint256(Utils.slice(arr, 448 + 5 * 128));
        ipProof.b = uint256(Utils.slice(arr, 480 + 5 * 128));
        proof.ipProof = ipProof;

        return proof;
    }
}

File 3 of 10: Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 4 of 10: ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "./IERC20.sol";
import "./IERC20Metadata.sol";
import "./Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The defaut value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) public {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        _approve(sender, _msgSender(), currentAllowance - amount);

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        _approve(_msgSender(), spender, currentAllowance - subtractedValue);

        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        _balances[sender] = senderBalance - amount;
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        _balances[account] = accountBalance - amount;
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

File 5 of 10: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 6 of 10: IERC20Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "./IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 7 of 10: InnerProductVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./Utils.sol";

contract InnerProductVerifier {
    using Utils for uint256;
    using Utils for Utils.G1Point;

    struct InnerProductStatement {
        Utils.G1Point[] hs; // "overridden" parameters.
        Utils.G1Point u;
        Utils.G1Point P;
    }

    struct InnerProductProof {
        Utils.G1Point[] ls;
        Utils.G1Point[] rs;
        uint256 a;
        uint256 b;
    }

    function verifyInnerProduct(Utils.G1Point[] memory hs, Utils.G1Point memory u, Utils.G1Point memory P, InnerProductProof memory proof, uint256 salt) public view returns (bool) {
        InnerProductStatement memory statement;
        statement.hs = hs;
        statement.u = u;
        statement.P = P;

        return verify(statement, proof, salt);
    }

    function gs(uint256 i) public pure returns (Utils.G1Point memory) {
        if (i == 0) return Utils.G1Point(0x0d1fff31f8dfb29333568b00628a0f92a752e8dee420dfede1be731810a807b9, 0x06c3001c74387dae9deddc75b76959ef5f98f1be48b0d9fc8ff6d7d76106b41b);
        if (i == 1) return Utils.G1Point(0x06e1b58cb1420e3d12020c5be2c4e48955efc64310ab10002164d0e2a767018e, 0x229facdebea78bd67f5b332bcdab7d692d0c4b18d77e92a8b3ffaee450c797c7);
        if (i == 2) return Utils.G1Point(0x22f32c65b43f3e770b793ea6e31c85d1aea2c41ea3204fc08a036004e5adef3a, 0x1d63e3737f864f05f62e2be0a6b7528b76cdabcda9703edc304c015480fb5543);
        if (i == 3) return Utils.G1Point(0x01df5e3e2818cfce850bd5d5f57872abc34b1315748e0280c4f0d3d6a40f94a9, 0x0d622581880ddba6a3911aa0df64f4fd816800c6dee483f07aa542a6e61534d5);
        if (i == 4) return Utils.G1Point(0x18d7f2117b1144f5035218384d817c6d1b4359497489a52bcf9d16c44624c1d0, 0x115f00d2f27917b5a3e8e6754451a4e990931516cf47e742949b8cbdda0e2c20);
        if (i == 5) return Utils.G1Point(0x093a9e9ba588d1b8eae48cf96b97def1fb8dccd519678520314e96d289ad1d11, 0x0f94a152edd0254ece896bc7e56708ba623c1ed3a27e4fd4c449f8e98fee1b5e);
        if (i == 6) return Utils.G1Point(0x0a7e8bc3cecaff1d9ec3e7d9c1fab7b5397bd6b6739c99bfe4bcb21d08d25934, 0x18d0114fa64774f712044e9a05b818fea4734db2b91fc7f049e120ce01c096be);
        if (i == 7) return Utils.G1Point(0x2095c16aea6e127aa3394d0124b545a45323708ae1c227575270d99b9900673a, 0x24c5a6afc36ef443197217591e084cdd69820401447163b5ab5f015801551a03);
        if (i == 8) return Utils.G1Point(0x041ee7d5aa6e191ba063876fda64b87728fa3ed39531400118b83372cbb5af75, 0x2dc2abc7d618ae4e1522f90d294c23627b6bc4f60093e8f07a7cd3869dac9836);
        if (i == 9) return Utils.G1Point(0x16dc75831b780dc5806dd5b8973f57f2f4ce8ad2a6bb152fbd9ccb58534115b4, 0x17b434c3b65a2f754c99f7bacf2f20bdcd7517a38e5eb301d2d88fe7735ebc9c);
        if (i == 10) return Utils.G1Point(0x18f1393a76e0af102ffeb380787ed950dc35b04b0cc6de1a6d806d4007b30dba, 0x1d640e43bab253bf176b69dffdb3ffc02640c591c392f400596155c8c3f668ef);
        if (i == 11) return Utils.G1Point(0x2bf3f58b4c957a8ae697aa57eb3f7428527fcb0c7e8d099efae80b97bde600e0, 0x14072f8bfdbe285b203cd0a2ebc1aed9ad1de309794226aee63c89397b187abf);
        if (i == 12) return Utils.G1Point(0x028eb6852c2827302aeb09def685b57bef74ff1a3ff72eda972e32b9ea80c32f, 0x1ba2dfb85a585de4b8a189f7b764f87c6f8e06c10d68d4493fc469504888837d);
        if (i == 13) return Utils.G1Point(0x19003e6b8f14f3583435527eac51a460c705dc6a042a2b7dd56b4f598af50886, 0x10e755ac3373f769e7e092f9eca276d911cd31833e82c70b8af09787e2c02d20);
        if (i == 14) return Utils.G1Point(0x0d493d4d49aa1a4fdf3bc3ba6d969b3e203741b3d570dbc511dd3171baf96f85, 0x1d103731795bcc57ddb8514e0e232446bfd9834f6a8ae9ff5235330d2a9e5ffa);
        if (i == 15) return Utils.G1Point(0x0ce438e766aae8c59b4006ee1749f40370fe5ec9fe29edce6b98e945915db97f, 0x02dba20dff83b373d2b47282e08d2c7883254a56701f2dbeea7ccc167ffb49a5);
        if (i == 16) return Utils.G1Point(0x05092110319650610a94fa0f9d50536404ba526380fc31b99ce95fbc1423a26f, 0x18a40146a4e79c2830d6d6e56314c538b0da4a2a72b7533e63f7d0a7e5ab2d22);
        if (i == 17) return Utils.G1Point(0x25b9ad9c4235b0a2e9f1b2ed20a5ca63814e1fb0eb95540c6f4f163c1a9fc2bd, 0x0a726ff7b655ad45468bcfd2d77f8aa0786ff3012d4edb77b5118f863dcdcbc0);
        if (i == 18) return Utils.G1Point(0x291ff28fa0a9840e230de0f0da725900bd18ce31d2369ffc80abbc4a77c1aff3, 0x1ffed5e9dffcd885ac867e2279836a11225548a8c253c47efe24f7d95a4bdd61);
        if (i == 19) return Utils.G1Point(0x0a01c96340d6bb4c94e028a522f74bef899d8f9d1a6d0b0d832f83275efa68de, 0x119c6a17ecb14721ac9eb331abccf2748868855fae43392391c37037d1b150a1);
        if (i == 20) return Utils.G1Point(0x2c846ad384d3ea063001f34fd60f0b8dc12b3b3ab7a5757f1d394f19850d8309, 0x1ff69942134c51e7315ccf1431e66fb5f70c24148c668f4fbe3861fbe535e39c);
        if (i == 21) return Utils.G1Point(0x0dafb5ae6accb6048e6dbc52f455c262dd2876b565792d68189618a3e630ade0, 0x236e97c592c19a2f2244f2938021671045787501e5a4a26de3580628ce37eb3b);
        if (i == 22) return Utils.G1Point(0x10df3e10a8d613058eae3278e2c80c3366c482354260f501447d15797de7378a, 0x10b25f7e075c93203ceba523afc44e0d5cd9e45a60b6dc11d2034180c40a004d);
        if (i == 23) return Utils.G1Point(0x1437b718d075d54da65adccdd3b6f758a5b76a9e5c5c7a13bf897a92e23fcde2, 0x0f0b988d70298608d02c73c410dc8b8bb6b95f0dde0dedcd5ea5692f0c07f3ed);
        if (i == 24) return Utils.G1Point(0x2705c71a95661231956d10845933f43cd973f4626e3a31dbf6287e01a00beb70, 0x27d09bd21d44269e2e7c85e1555fd351698eca14686d5aa969cb08e33db6691b);
        if (i == 25) return Utils.G1Point(0x1614dabf48099c315f244f8763f4b99ca2cef559781bf55e8e4d912d952edb4a, 0x16bf2f8fb1021b47be88ceb6fce08bf3b3a17026509cf9756c1a3fbf3b9d70bd);
        if (i == 26) return Utils.G1Point(0x21c448cfdcf007959812b2c5977cd4a808fa25408547e660c3fc12ed47501eb3, 0x14495c361cf9dc10222549bc258a76a20058f4795c2e65cd27f013c940b7dc7b);
        if (i == 27) return Utils.G1Point(0x1ac35f37ee0bfcb173d513ea7ac1daf5b46c6f70ce5f82a0396e7afac270ff35, 0x2f5f4480260b838ffcba9d34396fc116f75d1d5c24396ed4f7e01fd010ab9970);
        if (i == 28) return Utils.G1Point(0x0caaa12a18563703797d9be6ef74cbfb9e532cd027a1021f34ad337ce231e074, 0x2281c11389906c02bb15e995ffd6db136c3cdb4ec0829b88aec6db8dda05d5af);
        if (i == 29) return Utils.G1Point(0x1f3d91f1dfbbf01002a7e339ff6754b4ad2290493757475a062a75ec44bc3d50, 0x207b99884d9f7ca1e2f04457b90982ec6f8fb0a5b2ffd5b50d9cf4b2d850a920);
        if (i == 30) return Utils.G1Point(0x1fe58e4e4b1d155fb0a97dc9bae46f401edb2828dc4f96dafb86124cba424455, 0x01ad0a57feb7eeda4319a70ea56ded5e9fef71c78ff84413399d51f647d55113);
        if (i == 31) return Utils.G1Point(0x044e80195798557e870554d7025a8bc6b2ee9a05fa6ae016c3ab3b9e97af5769, 0x2c141a12135c4d14352fc60d851cdde147270f76405291b7c5d01da8f5dfed4d);
        if (i == 32) return Utils.G1Point(0x2883d31d84e605c858cf52260183f09d18bd55dc330f8bf12785e7a2563f8da4, 0x0e681e5c997f0bb609af7a95f920f23c4be78ded534832b514510518ede888b2);
        if (i == 33) return Utils.G1Point(0x2cdf5738c2690b263dfdc2b4235620d781bbff534d3363c4f3cfe5d1c67767c1, 0x15f4fb05e5facfd1988d61fd174a14b20e1dbe6ac37946e1527261be8742f5cf);
        if (i == 34) return Utils.G1Point(0x05542337765c24871e053bb8ec4e1baaca722f58b834426431c6d773788e9c66, 0x00e64d379c28d138d394f2cf9f0cc0b5a71e93a055bad23a2c6de74b217f3fac);
        if (i == 35) return Utils.G1Point(0x2efe9c1359531adb8a104242559a320593803c89a6ff0c6c493d7da5832603ab, 0x295898b3b86cf9e09e99d7f80e539078d3b5455bba60a5aa138b2995b75f0409);
        if (i == 36) return Utils.G1Point(0x2a3740ca39e35d23a5107fdae38209eaebdcd70ae740c873caf8b0b64d92db31, 0x05bab66121bccf807b1f776dc487057a5adf5f5791019996a2b7a2dbe1488797);
        if (i == 37) return Utils.G1Point(0x11ef5ef35b895540be39974ac6ad6697ef4337377f06092b6a668062bf0d8019, 0x1a42e3b4b73119a4be1dde36a8eaf553e88717cecb3fdfdc65ed2e728fda0782);
        if (i == 38) return Utils.G1Point(0x245aac96c5353f38ae92c6c17120e123c223b7eaca134658ebf584a8580ec096, 0x25ec55531155156663f8ba825a78f41f158def7b9d082e80259958277369ed08);
        if (i == 39) return Utils.G1Point(0x0fb13a72db572b1727954bb77d014894e972d7872678200a088febe8bd949986, 0x151af2ae374e02dec2b8c5dbde722ae7838d70ab4fd0857597b616a96a1db57c);
        if (i == 40) return Utils.G1Point(0x155fa64e4c8bf5f5aa53c1f5e44d961f688132c8545323d3bdc6c43a83220f89, 0x188507b59213816846bc9c763a93b52fb7ae8e8c8cc7549ce3358728415338a4);
        if (i == 41) return Utils.G1Point(0x28631525d5192140fd4fb04efbad8dcfddd5b8d0f5dc54442e5530989ef5b7fe, 0x0ad3a3d4845b4bc6a92563e72db2bc836168a295c56987c7bb1eea131a3760ac);
        if (i == 42) return Utils.G1Point(0x043b2963b1c5af8e2e77dfb89db7a0d907a40180929f3fd630a4a37811030b6d, 0x0721a4b292b41a3d948237bf076aabeedba377c43a10f78f368042ad155a3c91);
        if (i == 43) return Utils.G1Point(0x14bfb894e332921cf925f726f7c242a70dbd9366b68b50e14b618a86ecd45bd6, 0x09b1c50016fff7018a9483ce00b8ec3b6a0df36db21ae3b8282ca0b4be2e283c);
        if (i == 44) return Utils.G1Point(0x2758e65c03fdb27e58eb300bde8ada18372aa268b393ad5414e4db097ce9492d, 0x041f685536314ddd11441a3d7e01157f7ea7e474aae449dbba70c2edc70cd573);
        if (i == 45) return Utils.G1Point(0x191365dba9df566e0e6403fb9bcd6847c0964ea516c403fd88543a6a9b3fa1f2, 0x0ae815170115c7ce78323cbd9399735847552b379c2651af6fc29184e95eef7f);
        if (i == 46) return Utils.G1Point(0x027a2a874ba2ab278be899fe96528b6d39f9d090ef4511e68a3e4979bc18a526, 0x2272820981fe8a9f0f7c4910dd601cea6dd7045aa4d91843d3cf2afa959fbe68);
        if (i == 47) return Utils.G1Point(0x13feec071e0834433193b7be17ce48dec58d7610865d9876a08f91ea79c7e28d, 0x26325544133c7ec915c317ac358273eb2bf2e6b6119922d7f0ab0727e5eb9e64);
        if (i == 48) return Utils.G1Point(0x08e6096c8425c13b79e6fa38dffcc92c930d1d0bff9671303dbc0445e73c77bc, 0x03e884c8dc85f0d80baf968ae0516c1a7927808f83b4615665c67c59389db606);
        if (i == 49) return Utils.G1Point(0x1217ff3c630396cd92aa13aa6fee99880afc00f47162625274090278f09cbed3, 0x270b44f96accb061e9cad4a3341d72986677ed56157f3ba02520fdf484bb740d);
        if (i == 50) return Utils.G1Point(0x239128d2e007217328aae4e510c3d9fe1a3ef2b23212dfaf6f2dcb75ef08ed04, 0x2d5495372c759fdba858b7f6fa89a948eb4fd277bae9aebf9785c86ea3f9c07d);
        if (i == 51) return Utils.G1Point(0x305747313ea4d7d17bd14b69527094fa79bdc05c3cc837a668a97eb81cffd3d4, 0x0aa43bd7ad9090012e12f78ac3cb416903c2e1aabb61161ca261892465b3555d);
        if (i == 52) return Utils.G1Point(0x267742bd96caad20a76073d5060085103b7d29c88f0a0d842ef610472a1764ef, 0x0086485faeedd1ea8f6595b2edaf5f99044864271a178bd33e6d5b73b6d240a0);
        if (i == 53) return Utils.G1Point(0x00aed2e1ac448b854a44c7aa43cabb93d92316460c8f5eacb038f4cf554dfa01, 0x1b2ec095d370b234214a0c68fdfe8da1e06cbfdc5e889e2337ccb28c49089fcf);
        if (i == 54) return Utils.G1Point(0x06f37ac505236b2ed8c520ea36b0448229eb2f2536465b14e6e115dc810c6e39, 0x174db60e92b421e4d59c81e2c0666f7081067255c8e0d775e085278f34663490);
        if (i == 55) return Utils.G1Point(0x2af094e58a7961c4a1dba0685d8b01dacbb01f0fc0e7a648085a38aa380a7ab6, 0x108ade796501042dab10a83d878cf1deccf74e05edc92460b056d31f3e39fd53);
        if (i == 56) return Utils.G1Point(0x051ec23f1166a446caa4c8ff443470e98e753697fcceb4fbe5a49bf7a2db7199, 0x00f938707bf367e519d0c5efcdb61cc5a606901c0fbd4565abeeb5d020081d96);
        if (i == 57) return Utils.G1Point(0x1132459cf7287884b102467a71fad0992f1486178f7385ef159277b6e800239d, 0x257fedb1e126363af3fb3a80a4ad850d43041d64ef27cc5947730901f3019138);
        if (i == 58) return Utils.G1Point(0x14a571bbbb8d2a442855cde5fe6ed635d91668eded003d7698f9f744557887ea, 0x0f65f76e6fa6f6c7f765f947d905b015c3ad077219fc715c2ec40e37607c1041);
        if (i == 59) return Utils.G1Point(0x0e303c28b0649b95c624d01327a61fd144d29bfed6d3a1cf83216b45b78180cf, 0x229975c2e3aaba1d6203a5d94ea92605edb2af04f41e3783ec4e64755eeb1d1b);
        if (i == 60) return Utils.G1Point(0x05a62a2f1dfe368e81d9ae5fe150b9a57e0f85572194de27f48fec1c5f3b0dad, 0x200eb8097c91fe825adb0e3920e6bdff2e40114bd388298b85a0094a9a5bc654);
        if (i == 61) return Utils.G1Point(0x06545efc18dfc2f444e147c77ed572decd2b58d0668bbaaf0d31f1297cde6b99, 0x29ecbbeb81fe6c14279e9e46637ad286ba71e4c4e5da1416d8501e691f9e5bed);
        if (i == 62) return Utils.G1Point(0x045ce430f0713c29748e30d024cd703a5672633faebe1fd4d210b5af56a50e70, 0x0e3ec93722610f4599ffaac0db0c1b2bb446ff5aea5117710c271d1e64348844);
        if (i == 63) return Utils.G1Point(0x243de1ee802dd7a3ca9a991ec228fbbfb4973260f905b5106e5f738183d5cacd, 0x133d25bb8dc9f54932b9d6ee98e0432676f5278e9878967fbbd8f5dfc46df4f8);
    }

    function hs(uint256 i) public pure returns (Utils.G1Point memory) {
        if (i == 0) return Utils.G1Point(0x01d39aef1308fae84642befcdb6c07f655cc4d092f6a66f464cb9c959bff743a, 0x277420423ebed18174bd2730d4387b06c10958e564af6444333ac5b30767c59c);
        if (i == 1) return Utils.G1Point(0x2f1a6e72cf51c976df65f69457491bd852b4cf8a172183537dc413d0801bef0a, 0x0fc8845b156f86c3018d7a193c089c8d02ea38ba2cec11b1b6118a3b37f4cb08);
        if (i == 2) return Utils.G1Point(0x00f698cd9c34ea5fc62bd7d91c3a8b7f70bb12596d3c6d99b9be4d7acf2e72ea, 0x23abea6d9096d3c23f3aee1447570211efc5d2add2f310a2acaf3afc1faa0ed1);
        if (i == 3) return Utils.G1Point(0x06e93364d8080a84ab1dac7fa743b3f3f139f84c602cc67a899e3739abf11cc0, 0x2246590e06850a6f55b3e9bb81d7316fe7b08bef9f9a06d43b30226d626a979d);
        if (i == 4) return Utils.G1Point(0x1fb8f0bbb173c6d8f7ae2e1fa1e3770aa8c66fbed8d459d8e6fa972c990e0e22, 0x23d30ccd0b4747679bbd29620c3efb39ee1d7018b0281c448ad1501a5e04dc1a);
        if (i == 5) return Utils.G1Point(0x1b5f7c9fa9f3ef4adbed1f09bc6e151ba5e7c1d098c2d94e2dbe95897e6675cd, 0x23ff89ca0d326bd98629bf7ccf343ababdb330821a495b7624d8720fd1ead1e3);
        if (i == 6) return Utils.G1Point(0x2ffd2415cb4cd71a9f3cf4ed64d4a85d4d3eb06bfa10f98cb8a2ab7e2d96797c, 0x1d770c3d19238753457dd36280bd6685f6f214461a81aa95962f1c80a6c4168d);
        if (i == 7) return Utils.G1Point(0x2d344a9de673000e4108f8b6eb21b8cf39e223fad81cef47cd599b5e548a092b, 0x1abe37b046f84fa46b7629e432e298ae7dda657d2cdde851775431cab1d34402);
        if (i == 8) return Utils.G1Point(0x131bea29a212d81278492c44179c04f2a3f7e72151a0a4870b01e2fa96cdf84a, 0x0e5a783a7d6e044761fa10b801de33a1c4de8d4569f132b86a5be6aa13726127);
        if (i == 9) return Utils.G1Point(0x2e9de6196c9d4be4d765078245515d02b18ee6073ca0afb1afe98dcca2378d76, 0x1a5be81d26e9261e5072bb86f5cbd1dd8075316c8fec769ac839819a17ec3841);
        if (i == 10) return Utils.G1Point(0x21ccb04d241aa8108e9e5f2487fffe82debc69e4cff3a7ee292609fbe49cb6ad, 0x14d2e86d8bea6af2ad1cde303c9b2993a37c5b7bf0567278854ca666e61f2e80);
        if (i == 11) return Utils.G1Point(0x164314a3b09437cc1cd0f7726b8291be0bd293876093e51f989feab3238cfd85, 0x043bb4c392fbf35b9991d01ffaf6c59d7e72559ed7f338f85beebdf74ed3132f);
        if (i == 12) return Utils.G1Point(0x08a85c13ee191db8c043a21db38c016e27376d82063a93f8a6ff603b0f396433, 0x19be7f870a4bbd255c61ca01588bc3be2632c015753a3320309915e600d78a0a);
        if (i == 13) return Utils.G1Point(0x2090c3ab526ff54497f984b860682c77c0a89842f6612928cf4188c5c0f1ee20, 0x151a9c9fcdc438b3197d85ab51317d969d66e03fe26e05f6be466058cb8b7e65);
        if (i == 14) return Utils.G1Point(0x220b0c31ba1c84a2c1235d987e79d8fb1854fb59cce44719a13e4b83331da63b, 0x19a161498b4d63a027670174b424260b2180ccb02e05e4e061363ac3a87642da);
        if (i == 15) return Utils.G1Point(0x018eb881dd184f8abff3b91b50676a12945e205f200fdaf25ffb7e8c97385334, 0x1dea48b102351f75ce4977a6c3c908455a9e269aab69c3f66e642791052d0cfb);
        if (i == 16) return Utils.G1Point(0x07b0183a2450ccb5a001554ac3fe1a763bb69a0222316c1a553124a915cd0720, 0x282216c8c2711780ed3b24281fdd358d0e3d2e05e9cd1ab6842432f818a4a40c);
        if (i == 17) return Utils.G1Point(0x2b3f257e1258a3c2bda28be60fdc4cf2a74a19bb17d61783a91ec478d379e1a5, 0x1a8ddf17a83d7b89a6c7ae59601b736c4c7022f29c74700bd5d51cbd70b5051d);
        if (i == 18) return Utils.G1Point(0x0485fd181e30eef43c4356c6cdfb8957267795c838e6e64c52fd81a697dd8505, 0x17105695b4bfc555a55c8449182a6335584f971a0058172bd2b5441db3129843);
        if (i == 19) return Utils.G1Point(0x2008a80d7c60d7dc6e069b174efd31984a0933da7f89a574aae52e8805b40095, 0x052398552fb4706758b6eafb50bed493568670961058586735bca016e875e6ef);
        if (i == 20) return Utils.G1Point(0x119ff93e1bce3d5c7c57d1fea845e9335e04c729ec7a62ca2283d6c5dc0acc7c, 0x2042b68991a4d4c959df76947ef2594afb6735d760c3629825db8451b4830a3c);
        if (i == 21) return Utils.G1Point(0x0ed374dfa5daee92868812764c47ffd9c0c832abe09124f6f55283869d639eb7, 0x267767cb5017979990d9fa6db5f741de043afb70ee8a5e29045e926486f00858);
        if (i == 22) return Utils.G1Point(0x1c3786f37ee4f7eb9493551cea3c2a4e8ddcdd3c86e9f9ea2a41199efa1da476, 0x147d40e13345ec2f38975b09989d2c01954122796f83bfc19974ab647f754a32);
        if (i == 23) return Utils.G1Point(0x0040bf79ad3c473ffd4d7e15dbe0fa0a9b06e765a6d5adb372f98b8ea107f2c6, 0x17bf761b14f52da007532fcdf1bbdec180750af1b7b3804e29d6d45af62042f8);
        if (i == 24) return Utils.G1Point(0x01a9c26d59a9962250ce2b20b477884d11ce2c2404b749ceee59c51c2dcc0918, 0x1603d5448eb9b7528b247c0cdf8b0d9275322975bc7e4b13b8d0312cf032c467);
        if (i == 25) return Utils.G1Point(0x215ecf3e09641d5a38d4f510ed72e2ee586d4fbfc7e46411e1a3396f07b1e276, 0x28ece25edfb8c48631b861e838641f8e61e58afcf4e6c8f336c86fe5b7c0dfc9);
        if (i == 26) return Utils.G1Point(0x0beda6c3cbaec7226ed3bd6e0a27a626e0022b1afa820ac509e21b646f23dc60, 0x212f09e343da69ec34d90491282e69499c779973c0352126a38aabbf5783b288);
        if (i == 27) return Utils.G1Point(0x27f5c2199a6cebc34e3b5376b4db3ac6db08d2f302aa9b99f808e20a95e9ef8c, 0x0ccc4c0723e2a255e9b649eae9c16d72f4ddb97d088d7b3154c00e9a1dd94fe8);
        if (i == 28) return Utils.G1Point(0x2af5191d45c6ca76563c6f936f0cd2dcaa4311719675c2bb5f65d3df2270f636, 0x1252aca114b1fda7f43c06d1f2b60718e7bc99b8544138f9c67aad8dfca863d7);
        if (i == 29) return Utils.G1Point(0x13bdce5de7cf1c2250bac0be0d23d3be0140ce3838c8966ea2870e64b87adaee, 0x2f3770a6b5a9babcc5fa7cae8ffbb2a63ff312f2d3352e4fe8c173b12ff847e0);
        if (i == 30) return Utils.G1Point(0x18d1242b7bee604de29b4511814b02c8fd1519a4fc6daf9dbc95f8bb64ee097b, 0x0f828debef5bd4115c91f419718bdb59464bd8bb78fd0dc250d1efb1a51366df);
        if (i == 31) return Utils.G1Point(0x04b4102e8d3a2d3ba330257de8d18861db5652d685efb297d9c116eb1a7b1299, 0x08a3fd325f19ddebb53063d60fccdb8f0321fe41d4d93d98c65e05c9b4101aa0);
        if (i == 32) return Utils.G1Point(0x20f38c332b7117550a2462637fd38dfa08eb063e5bbc1838de2d8a933b052a5d, 0x0de3339a34e84bc8d57daf4fe55855a02df1c6fe4ce1cd07ca3060f67e1d75b2);
        if (i == 33) return Utils.G1Point(0x02f501714aa467e8b06ec808af8a3278f58faa7b87b678a1e36ee779adb01def, 0x1b8f1369d47a1d7b4da91b777bbcd7a2a4bde8ad09cc2eeeb9e8c0036ef5df47);
        if (i == 34) return Utils.G1Point(0x059c89b0e337c65e8132ac7c78f29d1a016edbff65da6663ef114f85bc414f20, 0x0b6e3d301ca62d0946299c6b79f2207479351ac27478901cdf5be144cf77435f);
        if (i == 35) return Utils.G1Point(0x02f51c34b66cd01304c185bcc087b9430beb0e6738e97491550740e18c262948, 0x27e42ced0bf3356a10e9685f1365a2ac3fdb3f3e89b9cd2f0309cd9ffcd6dfc0);
        if (i == 36) return Utils.G1Point(0x28c0affe0178e407e8196e3d0af3674aecc46a94342a97fec96d1eaa0e24ce3a, 0x1056737f11d45d9de7ff2d6de4ae31af9aa6a3ca2a0d56e5748059c7c39a02e7);
        if (i == 37) return Utils.G1Point(0x0100b2eb3ec56d3c557be418c4aabf0229ba4fb58c0bbb0756802e9f1573e245, 0x10a6e05da67b0cab1b2ded1f6e29f2c55279c738e18bbb91687fb046bac7789c);
        if (i == 38) return Utils.G1Point(0x0fe1fdb40a1c4b49772635241e37196fdca6a3cbd8ac2c550e1a48c90ec30029, 0x064ac2c20c146923131bab9ff316498a29fdce765a06c4a891f5b36993f52dba);
        if (i == 39) return Utils.G1Point(0x0c0aadc1d96e9b0b609e9f455c85ecf9506bbb7972f4adf58a3731f40cfd5d77, 0x1f3941c16c4c9da3c169c71abb9557d8b7b54d4b0998410d91d1b4a759f15028);
        if (i == 40) return Utils.G1Point(0x0a46308afef5a8af8f3b822aaa413d2961845a361f05cab5524144e74699cdec, 0x1035f4f2bf0b1ae6d0524d1309829c6d997cd7010650ca05a1bf585206e1aa3b);
        if (i == 41) return Utils.G1Point(0x1ccf854703b8608e10416032eaeadcc7ef236f2d1d33fec289d6db28db10b517, 0x1dbd7e3ed44a0fc339078bcb420b2641210a930a95eecc2aec0147a1abcbbb1a);
        if (i == 42) return Utils.G1Point(0x1408a19ef2793b8af811e95ffbdf901671a3b76bdc2203be5fde5475de4c54bc, 0x26431b0fbb7fb432a0edc0b247fee08d8f44a2abb0cb9b4b8a8a040bdea3cbf8);
        if (i == 43) return Utils.G1Point(0x2eb3aa4eb2234e4de8d30bcfeca595e758bc542da4ee111722fd6be47defd7e8, 0x1a7d7ab203974731e8f33dbbc7af481bbb64e47407e998d2d26dfa90a9dc321b);
        if (i == 44) return Utils.G1Point(0x1b6c0f4b954626f03f4fe59bc83ecc9ac2279d7d20746829583b66735cbb4830, 0x2eb200acc2138afec4e5f53438273760ca4d46bd0ebfa0155ae62a8055fee316);
        if (i == 45) return Utils.G1Point(0x0241820580d821b485c5d3f905cfc4a407881bbc7e041b4e50e2f628f88afc49, 0x2ee28fcaecd349babc91cb6fc9d65ed51dac6e2dd118898e3a0ee1bf0e94793d);
        if (i == 46) return Utils.G1Point(0x0b7b54391ce78ebf1aa3b4b2a75958f1702100aef8163810f89d0ad81c04ed78, 0x129075ea4b1ab58683019ab79340b2b090b9720721046332d8e0e80b2039406e);
        if (i == 47) return Utils.G1Point(0x18c8880c588c4dd3d657439a3357ff3bf0f44b9074d5d7aebb384fbac7e58090, 0x305de2ed95fe36ca48642098d98180b4ab92a03978fa6a038d80e546da989e6a);
        if (i == 48) return Utils.G1Point(0x00f185128b4341f79c914ef9739c830294df8da311891416babcc53e364ef245, 0x0a1ee67a755420fe0835770271142c883ebe3721140075a1677f2d57c6cec4b3);
        if (i == 49) return Utils.G1Point(0x2cf787f4957c6af6a6431d4a1577df0c71b6b44cca9771d8dee49ed83b024008, 0x25dfce7a0c6515b610f0b602d4083adfa436cbf1cce0e3dbec14338bee6ef501);
        if (i == 50) return Utils.G1Point(0x19934b0990d3b31864dcd3a9a7fe8ea20c87ef0abc3980c81035234b961b6c20, 0x2b8ca35cc74606b825937545131cb3c9248ec880b8df7c5eeac6d2be85aff646);
        if (i == 51) return Utils.G1Point(0x2adbdb8197cd82851b706df9c38a53950b1ba5953c8e7fcf3a037e4af817f706, 0x0cd2df6ffbde434614d0288d75ef6afd5d8f0c1b831d38b7de57785658b4bfe9);
        if (i == 52) return Utils.G1Point(0x1ee70de811fe6abb48823d75549e97bb81e3e98aea57e03b03164601b45a8889, 0x18ff1b711d742b30520fb8aeb174940d0e78ad926e0747cd3cf6cd9fdac1eb83);
        if (i == 53) return Utils.G1Point(0x2d831e2ba4c03354502c9ec8569eb4f1b7617b92e90e6bd2df617273793af02e, 0x1d838e04c75622032862a0ad64e997f99b64f9dce9dfd71b25214dc75371ef53);
        if (i == 54) return Utils.G1Point(0x0816128c1a69aacf266b28efd029bd12998f9abbfaa42c6b175d13452e81ec74, 0x084f00999de16016819beea6c19bade38d1802ac9ea2a59c70a94ab43676423f);
        if (i == 55) return Utils.G1Point(0x19fbf07d90fb1fc051cf76bc3ca6fb551463834456cac5a40a7e50dc492b6e07, 0x136cccfcd75ba252a946fc7e8d323ed9afdba4990600f97c8ea69ed72759c756);
        if (i == 56) return Utils.G1Point(0x2c0dca3a80d643d69ac2ccff2c16e727aa5eb81839a0b46e9b9f351941100e86, 0x0d90cee7e881d7484d76b29524af629358dc9795a2a789606fdec6d73e161435);
        if (i == 57) return Utils.G1Point(0x134b5d77b0c39945e9c8a7701bf5058183c5dc2010ab6ab6061243b2d748c4fa, 0x0d6297624431107091b2ccfc7c4f6964a14521ebecc4ca4687ad11ac439c9bc1);
        if (i == 58) return Utils.G1Point(0x1eff41015f3733fb8a295ff8a513d992d8723a159a294b5c444919ba22beb549, 0x0006941da956684261258a79a72fcf1b10e23e3f5844f808749fe10818cade97);
        if (i == 59) return Utils.G1Point(0x05d6227f2a9650a4b35412a9369f96155487d28e0f1827bce5fe2748e2b39c4f, 0x1640729260ba5f06592f23e8d2cf9b0a40ba5d090539b3d3f03e9a9bf8f6aad3);
        if (i == 60) return Utils.G1Point(0x166793ff28c5d31cf3c50fe736340af6cc6d6c80749bbcfd66db78ed80408e50, 0x2015c5c83fb2bb673aeb63e79928fa4c3a8ac6eb758b643e6bb9ff416ec6f3a5);
        if (i == 61) return Utils.G1Point(0x09ea2a4226678267f88c933e6f947fa16648a7710d169e715048e336d1b4129d, 0x26bb40f1b5f88a0a63acebd040aba0bbf85b03e04760bf5be723bd42d0f7d0ae);
        if (i == 62) return Utils.G1Point(0x0fe50825f829d35375a488cff7df34638241bce1a5b2f48c39635651e24c470d, 0x049b06661bb12c19ba643933a06d93035ecec6f53c61b8d4d2b39cc5c0459e68);
        if (i == 63) return Utils.G1Point(0x0b8871057f2a8bf0f794c099fba2481b9f39457d55d7e472e5dc994d69f0fbb8, 0x072c9e81fc2e118414a9fb6d9fff6e5b615f07fa980e3ce692a09bce95cc54f2);
    }

    struct IPAuxiliaries {
        uint256 o;
        uint256[] challenges;
        uint256[] otherExponents;
    }

    function verify(InnerProductStatement memory statement, InnerProductProof memory proof, uint256 salt) internal view returns (bool) {
        uint256 log_n = proof.ls.length;
        uint256 n = 2 ** log_n;

        IPAuxiliaries memory ipAuxiliaries; // for stacktoodeep
        ipAuxiliaries.o = salt; // could probably just access / overwrite the parameter directly.
        ipAuxiliaries.challenges = new uint256[](log_n);
        for (uint256 i = 0; i < log_n; i++) {
            ipAuxiliaries.o = uint256(keccak256(abi.encode(ipAuxiliaries.o, proof.ls[i], proof.rs[i]))).gMod(); // overwrites
            ipAuxiliaries.challenges[i] = ipAuxiliaries.o;
            statement.P = statement.P.pAdd(proof.ls[i].pMul(ipAuxiliaries.o.gExp(2)).pAdd(proof.rs[i].pMul(ipAuxiliaries.o.gInv().gExp(2))));
        }

        ipAuxiliaries.otherExponents = new uint256[](n);
        ipAuxiliaries.otherExponents[0] = 1;
        for (uint256 i = 0; i < log_n; i++) {
            ipAuxiliaries.otherExponents[0] = ipAuxiliaries.otherExponents[0].gMul(ipAuxiliaries.challenges[i]);
        }
        bool[] memory bitSet = new bool[](n);

        ipAuxiliaries.otherExponents[0] = ipAuxiliaries.otherExponents[0].gInv();
        for (uint256 i = 0; i < n / 2; ++i) {
            for (uint256 j = 0; (1 << j) + i < n; ++j) {
                uint256 i1 = i + (1 << j);
                if (!bitSet[i1]) {
                    uint256 temp = ipAuxiliaries.challenges[log_n - 1 - j].gExp(2);
                    ipAuxiliaries.otherExponents[i1] = ipAuxiliaries.otherExponents[i].gMul(temp);
                    bitSet[i1] = true;
                }
            }
        }

        Utils.G1Point memory gTemp;
        Utils.G1Point memory hTemp;
        for (uint256 i = 0; i < n; i++) {
            gTemp = gTemp.pAdd(gs(i).pMul(ipAuxiliaries.otherExponents[i]));
            hTemp = hTemp.pAdd(statement.hs[i].pMul(ipAuxiliaries.otherExponents[n - 1 - i]));
        }
        require(gTemp.pMul(proof.a).pAdd(hTemp.pMul(proof.b)).pAdd(statement.u.pMul(proof.a.gMul(proof.b))).pEqual(statement.P), "Inner product equality check failure.");

        return true;
    }
}


File 8 of 10: SuterBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./Utils.sol";
import "./TransferVerifier.sol";
import "./BurnVerifier.sol";

contract SuterBase {

    using Utils for uint256;
    using Utils for Utils.G1Point;

    address payable public suterAgency; 
    //Utils.G1Point public suterAgencyPublicKey;

    /* burn fee: 1/100 of burn amount */
    uint256 public BURN_FEE_MULTIPLIER = 1;
    uint256 public BURN_FEE_DIVIDEND = 100;
    /* transfer fee: 1/5 of gas */
    uint256 public TRANSFER_FEE_MULTIPLIER = 1;
    uint256 public TRANSFER_FEE_DIVIDEND = 5;

    //mapping(uint256 => bool) usedFeeStrategyNonces;


    TransferVerifier transferverifier;
    BurnVerifier burnverifier;
    //uint256 public epochLength = 12; 
    uint256 public epochLength = 24; 
    uint256 public epochBase = 0; // 0 for block, 1 for second (usually just for test)

    /* 
       The # of tokens that constitute one unit.
       Balances, funds, burns, and transfers are all interpreted in terms of unit, rather than token. 
    */
    uint256 public unit; 

    /*
       Max units that can be handled by suter.
       (No sload for constants...!)
    */
    uint256 public constant MAX = 2**32-1;

    uint256 public totalBalance = 0;
    uint256 public totalUsers = 0;
    uint256 public totalBurnFee = 0;
    uint256 public totalTransferFee = 0;
    uint256 public totalDeposits = 0;
    uint256 public totalFundCount = 0;
    

    mapping(bytes32 => Utils.G1Point[2]) acc; // main account mapping
    mapping(bytes32 => Utils.G1Point[2]) pending; // storage for pending transfers
    mapping(bytes32 => uint256) public lastRollOver;
    bytes32[] nonceSet; // would be more natural to use a mapping, but they can't be deleted / reset!
    uint256 public lastGlobalUpdate = 0; // will be also used as a proxy for "current epoch", seeing as rollovers will be anticipated
    //// not implementing account locking for now...revisit

    mapping(bytes32 => bytes) guess;

    event TransferOccurred(Utils.G1Point[] parties); // all parties will be notified, client can determine whether it was real or not.
    //// arg is still necessary for transfers---not even so much to know when you received a transfer, as to know when you got rolled over.
    event LogUint256(string label, uint256 indexed value);

    //constructor(address payable _suterAgency, Utils.G1Point memory _suterAgencyPublicKey, address _transfer, address _burn, uint256 _epochBase, uint256 _epochLength, uint256 _unit) public {
    constructor(address _transfer, address _burn, uint256 _unit) public {
        suterAgency = msg.sender;
        //suterAgencyPublicKey = _suterAgencyPublicKey;
        transferverifier = TransferVerifier(_transfer);
        burnverifier = BurnVerifier(_burn);
        //epochBase = _epochBase;
        //epochLength = _epochLength;
        unit = _unit;
    }

    function toUnitAmount(uint256 nativeAmount) internal view returns (uint256) {
        require(nativeAmount % unit == 0, "Native amount must be multiple of a unit.");
        uint256 amount = nativeAmount / unit;
        require(0 <= amount && amount <= MAX, "Amount out of range."); 
        return amount;
    }

    function toNativeAmount(uint256 unitAmount) internal view returns (uint256) {
        require(0 <= unitAmount && unitAmount <= MAX, "Amount out of range");
        return unitAmount * unit;
    }

    //function changeBurnFeeStrategy(uint256 multiplier, uint256 dividend, uint256 nonce, uint256 c, uint256 s) public {
        //require(!usedFeeStrategyNonces[nonce], "Fee strategy nonce has been used!");
        //usedFeeStrategyNonces[nonce] = true;

        //Utils.G1Point memory K = Utils.g().pMul(s).pAdd(suterAgencyPublicKey.pMul(c.gNeg()));
        //// Use block number to avoid replay attack
        //uint256 challenge = uint256(keccak256(abi.encode(address(this), multiplier, dividend, "burn", nonce, suterAgencyPublicKey, K))).gMod();
        ////uint256 challenge = uint256(keccak256(abi.encode(multiplier, dividend, "burn", block.number, suterAgencyPublicKey, K))).gMod();
        //require(challenge == c, string(abi.encodePacked("Invalid signature for changing the burn strategy.", Utils.uint2str(nonce))));
        //BURN_FEE_MULTIPLIER = multiplier;
        //BURN_FEE_DIVIDEND = dividend;
    //}

    function setBurnFeeStrategy(uint256 multiplier, uint256 dividend) public {
        require(msg.sender == suterAgency, "Permission denied: Only admin can change burn fee strategy.");
        BURN_FEE_MULTIPLIER = multiplier;
        BURN_FEE_DIVIDEND = dividend;
    }

    //function changeTransferFeeStrategy(uint256 multiplier, uint256 dividend, uint256 nonce, uint256 c, uint256 s) public {
        //require(!usedFeeStrategyNonces[nonce], "Fee strategy nonce has been used!");
        //usedFeeStrategyNonces[nonce] = true;

        //Utils.G1Point memory K = Utils.g().pMul(s).pAdd(suterAgencyPublicKey.pMul(c.gNeg()));
        //// Use block number to avoid replay attack
        //uint256 challenge = uint256(keccak256(abi.encode(address(this), multiplier, dividend, "transfer", nonce, suterAgencyPublicKey, K))).gMod();
        //require(challenge == c, "Invalid signature for changing the transfer strategy.");
        //TRANSFER_FEE_MULTIPLIER = multiplier;
        //TRANSFER_FEE_DIVIDEND = dividend;
    //}

    function setTransferFeeStrategy(uint256 multiplier, uint256 dividend) public {
        require(msg.sender == suterAgency, "Permission denied: Only admin can change transfer fee strategy.");
        TRANSFER_FEE_MULTIPLIER = multiplier;
        TRANSFER_FEE_DIVIDEND = dividend;
    }

    function setEpochBase (uint256 _epochBase) public {
        require(msg.sender == suterAgency, "Permission denied: Only admin can change epoch base.");
        epochBase = _epochBase;
    }

    function setEpochLength (uint256 _epochLength) public {
        require(msg.sender == suterAgency, "Permission denied: Only admin can change epoch length.");
        epochLength = _epochLength;
    }

    function setUnit (uint256 _unit) public {
        require(msg.sender == suterAgency, "Permission denied: Only admin can change unit.");
        unit = _unit;
    }

    function setSuterAgency (address payable _suterAgency) public {
        require(msg.sender == suterAgency, "Permission denied: Only admin can change agency.");
        suterAgency = _suterAgency;
    }

    function register(Utils.G1Point memory y, uint256 c, uint256 s) public {
        // allows y to participate. c, s should be a Schnorr signature on "this"
        Utils.G1Point memory K = Utils.g().pMul(s).pAdd(y.pMul(c.gNeg()));
        uint256 challenge = uint256(keccak256(abi.encode(address(this), y, K))).gMod();
        require(challenge == c, "Invalid registration signature!");
        bytes32 yHash = keccak256(abi.encode(y));
        require(!registered(yHash), "Account already registered!");
        // pending[yHash] = [y, Utils.g()]; // "not supported" yet, have to do the below

        /*
            The following initial value of pending[yHash] is equivalent to an ElGamal encryption of m = 0, with nonce r = 1:
            (mG + ry, rG) --> (y, G)
            If we don't set pending in this way, then we can't differentiate two cases:
            1. The account is not registered (both acc and pending are 0, because `mapping` has initial value for all keys)
            2. The account has a total balance of 0 (both acc and pending are 0)

            With such a setting, we can guarantee that, once an account is registered, its `acc` and `pending` can never (crytographically negligible) BOTH equal to Point zero.
            NOTE: `pending` can be reset to Point zero after a roll over.
        */
        pending[yHash][0] = y;
        pending[yHash][1] = Utils.g();

        totalUsers = totalUsers + 1;
    }

    function registered(bytes32 yHash) public view returns (bool) {
        Utils.G1Point memory zero = Utils.G1Point(0, 0);
        Utils.G1Point[2][2] memory scratch = [acc[yHash], pending[yHash]];
        return !(scratch[0][0].pEqual(zero) && scratch[0][1].pEqual(zero) && scratch[1][0].pEqual(zero) && scratch[1][1].pEqual(zero));
    }

    /**
      Get the current balances of accounts. If the given `epoch` is larger than the last roll over epoch, the returned balances
      will include pending transfers. 
    */
    function getBalance(Utils.G1Point[] memory y, uint256 epoch) view public returns (Utils.G1Point[2][] memory accounts) {
        // in this function and others, i have to use public + memory (and hence, a superfluous copy from calldata)
        // only because calldata structs aren't yet supported by solidity. revisit this in the future.
        uint256 size = y.length;
        accounts = new Utils.G1Point[2][](size);
        for (uint256 i = 0; i < size; i++) {
            bytes32 yHash = keccak256(abi.encode(y[i]));
            accounts[i] = acc[yHash];
            if (lastRollOver[yHash] < epoch) {
                Utils.G1Point[2] memory scratch = pending[yHash];
                accounts[i][0] = accounts[i][0].pAdd(scratch[0]);
                accounts[i][1] = accounts[i][1].pAdd(scratch[1]);
            }
        }
    }

    function getAccountState (Utils.G1Point memory y) public view returns (Utils.G1Point[2] memory y_available, Utils.G1Point[2] memory y_pending) {
        bytes32 yHash = keccak256(abi.encode(y));
        y_available = acc[yHash];
        y_pending = pending[yHash];
        return (y_available, y_pending);
    }

    function getGuess (Utils.G1Point memory y) public view returns (bytes memory y_guess) {
        bytes32 yHash = keccak256(abi.encode(y));
        y_guess = guess[yHash];
        return y_guess;
    }

    function rollOver(bytes32 yHash) internal {
        uint256 e = 0;
        if (epochBase == 0)
            e = block.number / epochLength;
        else if (epochBase == 1)
            e = block.timestamp / epochLength;
        else
            revert("Invalid epoch base.");

        if (lastRollOver[yHash] < e) {
            Utils.G1Point[2][2] memory scratch = [acc[yHash], pending[yHash]];
            acc[yHash][0] = scratch[0][0].pAdd(scratch[1][0]);
            acc[yHash][1] = scratch[0][1].pAdd(scratch[1][1]);
            // acc[yHash] = scratch[0]; // can't do this---have to do the above instead (and spend 2 sloads / stores)---because "not supported". revisit
            delete pending[yHash]; // pending[yHash] = [Utils.G1Point(0, 0), Utils.G1Point(0, 0)];
            lastRollOver[yHash] = e;
        }
        if (lastGlobalUpdate < e) {
            lastGlobalUpdate = e;
            delete nonceSet;
        }
    }

    function fundBase(Utils.G1Point memory y, uint256 amount, bytes memory encGuess) internal {

        require(amount <= MAX && totalBalance + amount <= MAX, "Fund pushes contract past maximum value.");
        totalBalance += amount;
        totalDeposits += amount;
        totalFundCount += 1;

        bytes32 yHash = keccak256(abi.encode(y));
        require(registered(yHash), "Account not yet registered.");
        rollOver(yHash);

        Utils.G1Point memory scratch = pending[yHash][0];
        scratch = scratch.pAdd(Utils.g().pMul(amount));
        pending[yHash][0] = scratch;

        guess[yHash] = encGuess;
    }

    function burnBase(Utils.G1Point memory y, uint256 amount, Utils.G1Point memory u, bytes memory proof, bytes memory encGuess) internal {
        //require(msg.value == BURN_FEE, "0.03 ETH for the burn transaction is expected to be sent along.");

        require(totalBalance >= amount, "Burn fails the sanity check.");
        totalBalance -= amount;
        

        bytes32 yHash = keccak256(abi.encode(y));
        require(registered(yHash), "Account not yet registered.");
        rollOver(yHash);

        Utils.G1Point[2] memory scratch = pending[yHash];
        pending[yHash][0] = scratch[0].pAdd(Utils.g().pMul(amount.gNeg()));

        scratch = acc[yHash]; // simulate debit of acc---just for use in verification, won't be applied
        scratch[0] = scratch[0].pAdd(Utils.g().pMul(amount.gNeg()));
        bytes32 uHash = keccak256(abi.encode(u));
        for (uint256 i = 0; i < nonceSet.length; i++) {
            require(nonceSet[i] != uHash, "Nonce already seen!");
        }
        nonceSet.push(uHash);

        guess[yHash] = encGuess;

        require(burnverifier.verifyBurn(scratch[0], scratch[1], y, lastGlobalUpdate, u, msg.sender, proof), "Burn proof verification failed!");
        //suterAgency.transfer(BURN_FEE);
    }

    function transfer(Utils.G1Point[] memory C, Utils.G1Point memory D, 
                      Utils.G1Point[] memory y, Utils.G1Point memory u, 
                      bytes memory proof) public payable {

        uint256 startGas = gasleft();

        // TODO: check that sender and receiver should NOT be equal.
        uint256 size = y.length;
        Utils.G1Point[] memory CLn = new Utils.G1Point[](size);
        Utils.G1Point[] memory CRn = new Utils.G1Point[](size);
        require(C.length == size, "Input array length mismatch!");


        for (uint256 i = 0; i < size; i++) {
            bytes32 yHash = keccak256(abi.encode(y[i]));
            require(registered(yHash), "Account not yet registered.");
            rollOver(yHash);
            Utils.G1Point[2] memory scratch = pending[yHash];
            pending[yHash][0] = scratch[0].pAdd(C[i]);
            pending[yHash][1] = scratch[1].pAdd(D);
            // pending[yHash] = scratch; // can't do this, so have to use 2 sstores _anyway_ (as in above)

            scratch = acc[yHash];
            CLn[i] = scratch[0].pAdd(C[i]);
            CRn[i] = scratch[1].pAdd(D);
        }

        bytes32 uHash = keccak256(abi.encode(u));
        for (uint256 i = 0; i < nonceSet.length; i++) {
            require(nonceSet[i] != uHash, "Nonce already seen!");
        }
        nonceSet.push(uHash);

        require(transferverifier.verifyTransfer(CLn, CRn, C, D, y, lastGlobalUpdate, u, proof), "Transfer proof verification failed!");

        uint256 usedGas = startGas - gasleft();
        
        uint256 fee = (usedGas * TRANSFER_FEE_MULTIPLIER / TRANSFER_FEE_DIVIDEND) * tx.gasprice;
        if (fee > 0) {
            require(msg.value >= fee, "Not enough fee sent with the transfer transaction.");
            suterAgency.transfer(fee);
            totalTransferFee = totalTransferFee + fee;
        }
        msg.sender.transfer(msg.value - fee);

        emit TransferOccurred(y);
    }
}



File 9 of 10: TransferVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./Utils.sol";
import "./InnerProductVerifier.sol";

contract TransferVerifier {
    using Utils for uint256;
    using Utils for Utils.G1Point;

    uint256 constant UNITY = 0x14a3074b02521e3b1ed9852e5028452693e87be4e910500c7ba9bbddb2f46edd; // primitive 2^28th root of unity modulo q.

    InnerProductVerifier ip;

    struct TransferStatement {
        Utils.G1Point[] CLn;
        Utils.G1Point[] CRn;
        Utils.G1Point[] C;
        Utils.G1Point D;
        Utils.G1Point[] y;
        uint256 epoch;
        Utils.G1Point u;
    }

    struct TransferProof {
        Utils.G1Point BA;
        Utils.G1Point BS;
        Utils.G1Point A;
        Utils.G1Point B;

        Utils.G1Point[] CLnG;
        Utils.G1Point[] CRnG;
        Utils.G1Point[] C_0G;
        Utils.G1Point[] DG;
        Utils.G1Point[] y_0G;
        Utils.G1Point[] gG;
        Utils.G1Point[] C_XG;
        Utils.G1Point[] y_XG;

        uint256[] f;
        uint256 z_A;
        uint256 z_C;
        uint256 z_E;

        Utils.G1Point[2] tCommits;
        uint256 tHat;
        uint256 mu;

        uint256 c;
        uint256 s_sk;
        uint256 s_r;
        uint256 s_b;
        uint256 s_tau;

        InnerProductVerifier.InnerProductProof ipProof;
    }

    constructor(address _ip) public {
        ip = InnerProductVerifier(_ip);
    }

    function verifyTransfer(Utils.G1Point[] memory CLn, Utils.G1Point[] memory CRn, Utils.G1Point[] memory C, Utils.G1Point memory D, Utils.G1Point[] memory y, uint256 epoch, Utils.G1Point memory u, bytes memory proof) public view returns (bool) {
        TransferStatement memory statement;
        statement.CLn = CLn; // do i need to allocate / set size?!
        statement.CRn = CRn;
        statement.C = C;
        statement.D = D;
        statement.y = y;
        statement.epoch = epoch;
        statement.u = u;
        TransferProof memory zetherProof = unserialize(proof);
        return verify(statement, zetherProof);
    }

    struct TransferAuxiliaries {
        uint256 y;
        uint256[64] ys;
        uint256 z;
        uint256[2] zs; // [z^2, z^3]
        uint256[64] twoTimesZSquared;
        uint256 zSum;
        uint256 x;
        uint256 t;
        uint256 k;
        Utils.G1Point tEval;
    }

    struct SigmaAuxiliaries {
        uint256 c;
        Utils.G1Point A_y;
        Utils.G1Point A_D;
        Utils.G1Point A_b;
        Utils.G1Point A_X;
        Utils.G1Point A_t;
        Utils.G1Point gEpoch;
        Utils.G1Point A_u;
    }

    struct AnonAuxiliaries {
        uint256 m;
        uint256 N;
        uint256 v;
        uint256 w;
        uint256 vPow;
        uint256 wPow;
        uint256[2][] f; // could just allocate extra space in the proof?
        uint256[2][] r; // each poly is an array of length N. evaluations of prods
        Utils.G1Point temp;
        Utils.G1Point CLnR;
        Utils.G1Point CRnR;
        Utils.G1Point[2][] CR;
        Utils.G1Point[2][] yR;
        Utils.G1Point C_XR;
        Utils.G1Point y_XR;
        Utils.G1Point gR;
        Utils.G1Point DR;
    }

    struct IPAuxiliaries {
        Utils.G1Point P;
        Utils.G1Point u_x;
        Utils.G1Point[] hPrimes;
        Utils.G1Point hPrimeSum;
        uint256 o;
    }

    function gSum() internal pure returns (Utils.G1Point memory) {
        return Utils.G1Point(0x00715f13ea08d6b51bedcde3599d8e12163e090921309d5aafc9b5bfaadbcda0, 0x27aceab598af7bf3d16ca9d40fe186c489382c21bb9d22b19cb3af8b751b959f);
    }

    function verify(TransferStatement memory statement, TransferProof memory proof) internal view returns (bool) {
        uint256 statementHash = uint256(keccak256(abi.encode(statement.CLn, statement.CRn, statement.C, statement.D, statement.y, statement.epoch))).gMod();

        AnonAuxiliaries memory anonAuxiliaries;
        anonAuxiliaries.v = uint256(keccak256(abi.encode(statementHash, proof.BA, proof.BS, proof.A, proof.B))).gMod();
        anonAuxiliaries.w = uint256(keccak256(abi.encode(anonAuxiliaries.v, proof.CLnG, proof.CRnG, proof.C_0G, proof.DG, proof.y_0G, proof.gG, proof.C_XG, proof.y_XG))).gMod();
        anonAuxiliaries.m = proof.f.length / 2;
        anonAuxiliaries.N = 2 ** anonAuxiliaries.m;
        anonAuxiliaries.f = new uint256[2][](2 * anonAuxiliaries.m);
        for (uint256 k = 0; k < 2 * anonAuxiliaries.m; k++) {
            anonAuxiliaries.f[k][1] = proof.f[k];
            anonAuxiliaries.f[k][0] = anonAuxiliaries.w.gSub(proof.f[k]);
        }

        for (uint256 k = 0; k < 2 * anonAuxiliaries.m; k++) {
            anonAuxiliaries.temp = anonAuxiliaries.temp.pAdd(ip.gs(k).pMul(anonAuxiliaries.f[k][1]));
            anonAuxiliaries.temp = anonAuxiliaries.temp.pAdd(ip.gs(k + 2 * anonAuxiliaries.m).pMul(anonAuxiliaries.f[k][1].gMul(anonAuxiliaries.w.gSub(anonAuxiliaries.f[k][1]))));
        }
        anonAuxiliaries.temp = anonAuxiliaries.temp.pAdd(ip.gs(4 * anonAuxiliaries.m).pMul(anonAuxiliaries.f[0][1].gMul(anonAuxiliaries.f[anonAuxiliaries.m][1])).pAdd(ip.gs(1 + 4 * anonAuxiliaries.m).pMul(anonAuxiliaries.f[0][0].gMul(anonAuxiliaries.f[anonAuxiliaries.m][0]))));
        require(proof.B.pMul(anonAuxiliaries.w).pAdd(proof.A).pEqual(anonAuxiliaries.temp.pAdd(Utils.h().pMul(proof.z_A))), "Recovery failure for B^w * A.");

        anonAuxiliaries.r = assemblePolynomials(anonAuxiliaries.f);

        anonAuxiliaries.CR = assembleConvolutions(anonAuxiliaries.r, statement.C);
        anonAuxiliaries.yR = assembleConvolutions(anonAuxiliaries.r, statement.y);
        for (uint256 i = 0; i < anonAuxiliaries.N; i++) {
            anonAuxiliaries.CLnR = anonAuxiliaries.CLnR.pAdd(statement.CLn[i].pMul(anonAuxiliaries.r[i][0]));
            anonAuxiliaries.CRnR = anonAuxiliaries.CRnR.pAdd(statement.CRn[i].pMul(anonAuxiliaries.r[i][0]));
        }
        anonAuxiliaries.vPow = 1;
        for (uint256 i = 0; i < anonAuxiliaries.N; i++) {
            anonAuxiliaries.C_XR = anonAuxiliaries.C_XR.pAdd(anonAuxiliaries.CR[i / 2][i % 2].pMul(anonAuxiliaries.vPow));
            anonAuxiliaries.y_XR = anonAuxiliaries.y_XR.pAdd(anonAuxiliaries.yR[i / 2][i % 2].pMul(anonAuxiliaries.vPow));
            if (i > 0) {
                anonAuxiliaries.vPow = anonAuxiliaries.vPow.gMul(anonAuxiliaries.v);
            }
        }
        anonAuxiliaries.wPow = 1;
        for (uint256 k = 0; k < anonAuxiliaries.m; k++) {
            anonAuxiliaries.CLnR = anonAuxiliaries.CLnR.pAdd(proof.CLnG[k].pMul(anonAuxiliaries.wPow.gNeg()));
            anonAuxiliaries.CRnR = anonAuxiliaries.CRnR.pAdd(proof.CRnG[k].pMul(anonAuxiliaries.wPow.gNeg()));
            anonAuxiliaries.CR[0][0] = anonAuxiliaries.CR[0][0].pAdd(proof.C_0G[k].pMul(anonAuxiliaries.wPow.gNeg()));
            anonAuxiliaries.DR = anonAuxiliaries.DR.pAdd(proof.DG[k].pMul(anonAuxiliaries.wPow.gNeg()));
            anonAuxiliaries.yR[0][0] = anonAuxiliaries.yR[0][0].pAdd(proof.y_0G[k].pMul(anonAuxiliaries.wPow.gNeg()));
            anonAuxiliaries.gR = anonAuxiliaries.gR.pAdd(proof.gG[k].pMul(anonAuxiliaries.wPow.gNeg()));
            anonAuxiliaries.C_XR = anonAuxiliaries.C_XR.pAdd(proof.C_XG[k].pMul(anonAuxiliaries.wPow.gNeg()));
            anonAuxiliaries.y_XR = anonAuxiliaries.y_XR.pAdd(proof.y_XG[k].pMul(anonAuxiliaries.wPow.gNeg()));

            anonAuxiliaries.wPow = anonAuxiliaries.wPow.gMul(anonAuxiliaries.w);
        }
        anonAuxiliaries.DR = anonAuxiliaries.DR.pAdd(statement.D.pMul(anonAuxiliaries.wPow));
        anonAuxiliaries.gR = anonAuxiliaries.gR.pAdd(Utils.g().pMul(anonAuxiliaries.wPow));

        TransferAuxiliaries memory zetherAuxiliaries;
        zetherAuxiliaries.y = uint256(keccak256(abi.encode(anonAuxiliaries.w))).gMod();
        zetherAuxiliaries.ys[0] = 1;
        zetherAuxiliaries.k = 1;
        for (uint256 i = 1; i < 64; i++) {
            zetherAuxiliaries.ys[i] = zetherAuxiliaries.ys[i - 1].gMul(zetherAuxiliaries.y);
            zetherAuxiliaries.k = zetherAuxiliaries.k.gAdd(zetherAuxiliaries.ys[i]);
        }
        zetherAuxiliaries.z = uint256(keccak256(abi.encode(zetherAuxiliaries.y))).gMod();
        zetherAuxiliaries.zs = [zetherAuxiliaries.z.gExp(2), zetherAuxiliaries.z.gExp(3)];        
        zetherAuxiliaries.zSum = zetherAuxiliaries.zs[0].gAdd(zetherAuxiliaries.zs[1]).gMul(zetherAuxiliaries.z);
        zetherAuxiliaries.k = zetherAuxiliaries.k.gMul(zetherAuxiliaries.z.gSub(zetherAuxiliaries.zs[0])).gSub(zetherAuxiliaries.zSum.gMul(2 ** 32).gSub(zetherAuxiliaries.zSum));
        zetherAuxiliaries.t = proof.tHat.gSub(zetherAuxiliaries.k); // t = tHat - delta(y, z)
        for (uint256 i = 0; i < 32; i++) {
            zetherAuxiliaries.twoTimesZSquared[i] = zetherAuxiliaries.zs[0].gMul(2 ** i);
            zetherAuxiliaries.twoTimesZSquared[i + 32] = zetherAuxiliaries.zs[1].gMul(2 ** i);
        }

        zetherAuxiliaries.x = uint256(keccak256(abi.encode(zetherAuxiliaries.z, proof.tCommits))).gMod();
        zetherAuxiliaries.tEval = proof.tCommits[0].pMul(zetherAuxiliaries.x).pAdd(proof.tCommits[1].pMul(zetherAuxiliaries.x.gMul(zetherAuxiliaries.x))); // replace with "commit"?

        SigmaAuxiliaries memory sigmaAuxiliaries;
        sigmaAuxiliaries.A_y = anonAuxiliaries.gR.pMul(proof.s_sk).pAdd(anonAuxiliaries.yR[0][0].pMul(proof.c.gNeg()));
        sigmaAuxiliaries.A_D = Utils.g().pMul(proof.s_r).pAdd(statement.D.pMul(proof.c.gNeg())); // add(mul(anonAuxiliaries.gR, proof.s_r), mul(anonAuxiliaries.DR, proof.c.neg()));
        sigmaAuxiliaries.A_b = Utils.g().pMul(proof.s_b).pAdd(anonAuxiliaries.DR.pMul(zetherAuxiliaries.zs[0].gNeg()).pAdd(anonAuxiliaries.CRnR.pMul(zetherAuxiliaries.zs[1])).pMul(proof.s_sk).pAdd(anonAuxiliaries.CR[0][0].pMul(zetherAuxiliaries.zs[0].gNeg()).pAdd(anonAuxiliaries.CLnR.pMul(zetherAuxiliaries.zs[1])).pMul(proof.c.gNeg())));
        sigmaAuxiliaries.A_X = anonAuxiliaries.y_XR.pMul(proof.s_r).pAdd(anonAuxiliaries.C_XR.pMul(proof.c.gNeg()));
        sigmaAuxiliaries.A_t = Utils.g().pMul(zetherAuxiliaries.t).pAdd(zetherAuxiliaries.tEval.pNeg()).pMul(proof.c.gMul(anonAuxiliaries.wPow)).pAdd(Utils.h().pMul(proof.s_tau)).pAdd(Utils.g().pMul(proof.s_b.gNeg()));
        sigmaAuxiliaries.gEpoch = Utils.mapInto("Suter", statement.epoch);
        sigmaAuxiliaries.A_u = sigmaAuxiliaries.gEpoch.pMul(proof.s_sk).pAdd(statement.u.pMul(proof.c.gNeg()));

        sigmaAuxiliaries.c = uint256(keccak256(abi.encode(zetherAuxiliaries.x, sigmaAuxiliaries.A_y, sigmaAuxiliaries.A_D, sigmaAuxiliaries.A_b, sigmaAuxiliaries.A_X, sigmaAuxiliaries.A_t, sigmaAuxiliaries.A_u))).gMod();
        require(sigmaAuxiliaries.c == proof.c, string(abi.encodePacked("Sigma protocol challenge equality failure. Epoch: ", Utils.uint2str(statement.epoch))));

        IPAuxiliaries memory ipAuxiliaries;
        ipAuxiliaries.o = uint256(keccak256(abi.encode(sigmaAuxiliaries.c))).gMod();
        ipAuxiliaries.u_x = Utils.g().pMul(ipAuxiliaries.o);
        ipAuxiliaries.hPrimes = new Utils.G1Point[](64);
        for (uint256 i = 0; i < 64; i++) {
            ipAuxiliaries.hPrimes[i] = ip.hs(i).pMul(zetherAuxiliaries.ys[i].gInv());
            ipAuxiliaries.hPrimeSum = ipAuxiliaries.hPrimeSum.pAdd(ipAuxiliaries.hPrimes[i].pMul(zetherAuxiliaries.ys[i].gMul(zetherAuxiliaries.z).gAdd(zetherAuxiliaries.twoTimesZSquared[i])));
        }
        ipAuxiliaries.P = proof.BA.pAdd(proof.BS.pMul(zetherAuxiliaries.x)).pAdd(gSum().pMul(zetherAuxiliaries.z.gNeg())).pAdd(ipAuxiliaries.hPrimeSum);
        ipAuxiliaries.P = ipAuxiliaries.P.pAdd(Utils.h().pMul(proof.mu.gNeg()));
        ipAuxiliaries.P = ipAuxiliaries.P.pAdd(ipAuxiliaries.u_x.pMul(proof.tHat));
        require(ip.verifyInnerProduct(ipAuxiliaries.hPrimes, ipAuxiliaries.u_x, ipAuxiliaries.P, proof.ipProof, ipAuxiliaries.o), "Inner product proof verification failed.");

        return true;
    }

    function assemblePolynomials(uint256[2][] memory f) internal view returns (uint256[2][] memory result) {
        uint256 m = f.length / 2;
        uint256 N = 2 ** m;
        result = new uint256[2][](N);
        for (uint256 i = 0; i < 2; i++) {
            uint256[] memory half = recursivePolynomials(i * m, (i + 1) * m, 1, f);
            for (uint256 j = 0; j < N; j++) {
                result[j][i] = half[j];
            }
        }
    }

    function recursivePolynomials(uint256 baseline, uint256 current, uint256 accum, uint256[2][] memory f) internal view returns (uint256[] memory result) {
        // have to do a bunch of re-allocating because solidity won't let me have something which is internal and also modifies (internal) state. (?)
        uint256 size = 2 ** (current - baseline); // size is at least 2...
        result = new uint256[](size);

        if (current == baseline) {
            result[0] = accum;
            return result;
        }
        current = current - 1;

        uint256[] memory left = recursivePolynomials(baseline, current, accum.gMul(f[current][0]), f);
        uint256[] memory right = recursivePolynomials(baseline, current, accum.gMul(f[current][1]), f);
        for (uint256 i = 0; i < size / 2; i++) {
            result[i] = left[i];
            result[i + size / 2] = right[i];
        }
    }

    function assembleConvolutions(uint256[2][] memory exponent, Utils.G1Point[] memory base) internal view returns (Utils.G1Point[2][] memory result) {
        // exponent is two "rows" (actually columns).
        // will return two rows, each of half the length of the exponents;
        // namely, we will return the Hadamards of "base" by the even circular shifts of "exponent"'s rows.
        uint256 size = exponent.length;
        uint256 half = size / 2;
        result = new Utils.G1Point[2][](half); // assuming that this is necessary even when return is declared up top

        Utils.G1Point[] memory base_fft = fft(base, false);

        uint256[] memory exponent_fft = new uint256[](size);
        for (uint256 i = 0; i < 2; i++) {
            for (uint256 j = 0; j < size; j++) {
                exponent_fft[j] = exponent[(size - j) % size][i]; // convolutional flip plus copy
            }

            exponent_fft = fft(exponent_fft);
            Utils.G1Point[] memory inverse_fft = new Utils.G1Point[](half);
            uint256 compensation = 2;
            compensation = compensation.gInv();
            for (uint256 j = 0; j < half; j++) { // Hadamard
                inverse_fft[j] = base_fft[j].pMul(exponent_fft[j]).pAdd(base_fft[j + half].pMul(exponent_fft[j + half])).pMul(compensation);
            }

            inverse_fft = fft(inverse_fft, true);
            for (uint256 j = 0; j < half; j++) {
                result[j][i] = inverse_fft[j];
            }
        }
    }

    function fft(Utils.G1Point[] memory input, bool inverse) internal view returns (Utils.G1Point[] memory result) {
        uint256 size = input.length;
        if (size == 1) {
            return input;
        }
        require(size % 2 == 0, "Input size is not a power of 2!");

        uint256 omega = UNITY.gExp(2**28 / size);
        uint256 compensation = 1;
        if (inverse) {
            omega = omega.gInv();
            compensation = 2;
        }
        compensation = compensation.gInv();
        Utils.G1Point[] memory even = fft(extract(input, 0), inverse);
        Utils.G1Point[] memory odd = fft(extract(input, 1), inverse);
        uint256 omega_run = 1;
        result = new Utils.G1Point[](size);
        for (uint256 i = 0; i < size / 2; i++) {
            Utils.G1Point memory temp = odd[i].pMul(omega_run);
            result[i] = even[i].pAdd(temp).pMul(compensation);
            result[i + size / 2] = even[i].pAdd(temp.pNeg()).pMul(compensation);
            omega_run = omega_run.gMul(omega);
        }
    }

    function extract(Utils.G1Point[] memory input, uint256 parity) internal pure returns (Utils.G1Point[] memory result) {
        result = new Utils.G1Point[](input.length / 2);
        for (uint256 i = 0; i < input.length / 2; i++) {
            result[i] = input[2 * i + parity];
        }
    }

    function fft(uint256[] memory input) internal view returns (uint256[] memory result) {
        uint256 size = input.length;
        if (size == 1) {
            return input;
        }
        require(size % 2 == 0, "Input size is not a power of 2!");

        uint256 omega = UNITY.gExp(2**28 / size);
        uint256[] memory even = fft(extract(input, 0));
        uint256[] memory odd = fft(extract(input, 1));
        uint256 omega_run = 1;
        result = new uint256[](size);
        for (uint256 i = 0; i < size / 2; i++) {
            uint256 temp = odd[i].gMul(omega_run);
            result[i] = even[i].gAdd(temp);
            result[i + size / 2] = even[i].gSub(temp);
            omega_run = omega_run.gMul(omega);
        }
    }

    function extract(uint256[] memory input, uint256 parity) internal pure returns (uint256[] memory result) {
        result = new uint256[](input.length / 2);
        for (uint256 i = 0; i < input.length / 2; i++) {
            result[i] = input[2 * i + parity];
        }
    }

    function unserialize(bytes memory arr) internal pure returns (TransferProof memory proof) {
        proof.BA = Utils.G1Point(Utils.slice(arr, 0), Utils.slice(arr, 32));
        proof.BS = Utils.G1Point(Utils.slice(arr, 64), Utils.slice(arr, 96));
        proof.A = Utils.G1Point(Utils.slice(arr, 128), Utils.slice(arr, 160));
        proof.B = Utils.G1Point(Utils.slice(arr, 192), Utils.slice(arr, 224));

        uint256 m = (arr.length - 1472) / 576;
        proof.CLnG = new Utils.G1Point[](m);
        proof.CRnG = new Utils.G1Point[](m);
        proof.C_0G = new Utils.G1Point[](m);
        proof.DG = new Utils.G1Point[](m);
        proof.y_0G = new Utils.G1Point[](m);
        proof.gG = new Utils.G1Point[](m);
        proof.C_XG = new Utils.G1Point[](m);
        proof.y_XG = new Utils.G1Point[](m);
        proof.f = new uint256[](2 * m);
        for (uint256 k = 0; k < m; k++) {
            proof.CLnG[k] = Utils.G1Point(Utils.slice(arr, 256 + k * 64), Utils.slice(arr, 288 + k * 64));
            proof.CRnG[k] = Utils.G1Point(Utils.slice(arr, 256 + (m + k) * 64), Utils.slice(arr, 288 + (m + k) * 64));
            proof.C_0G[k] = Utils.G1Point(Utils.slice(arr, 256 + m * 128 + k * 64), Utils.slice(arr, 288 + m * 128 + k * 64));
            proof.DG[k] = Utils.G1Point(Utils.slice(arr, 256 + m * 192 + k * 64), Utils.slice(arr, 288 + m * 192 + k * 64));
            proof.y_0G[k] = Utils.G1Point(Utils.slice(arr, 256 + m * 256 + k * 64), Utils.slice(arr, 288 + m * 256 + k * 64));
            proof.gG[k] = Utils.G1Point(Utils.slice(arr, 256 + m * 320 + k * 64), Utils.slice(arr, 288 + m * 320 + k * 64));
            proof.C_XG[k] = Utils.G1Point(Utils.slice(arr, 256 + m * 384 + k * 64), Utils.slice(arr, 288 + m * 384 + k * 64));
            proof.y_XG[k] = Utils.G1Point(Utils.slice(arr, 256 + m * 448 + k * 64), Utils.slice(arr, 288 + m * 448 + k * 64));
            proof.f[k] = uint256(Utils.slice(arr, 256 + m * 512 + k * 32));
            proof.f[k + m] = uint256(Utils.slice(arr, 256 + m * 544 + k * 32));
        }
        uint256 starting = m * 576;
        proof.z_A = uint256(Utils.slice(arr, 256 + starting));

        proof.tCommits = [Utils.G1Point(Utils.slice(arr, 288 + starting), Utils.slice(arr, 320 + starting)), Utils.G1Point(Utils.slice(arr, 352 + starting), Utils.slice(arr, 384 + starting))];
        proof.tHat = uint256(Utils.slice(arr, 416 + starting));
        proof.mu = uint256(Utils.slice(arr, 448 + starting));

        proof.c = uint256(Utils.slice(arr, 480 + starting));
        proof.s_sk = uint256(Utils.slice(arr, 512 + starting));
        proof.s_r = uint256(Utils.slice(arr, 544 + starting));
        proof.s_b = uint256(Utils.slice(arr, 576 + starting));
        proof.s_tau = uint256(Utils.slice(arr, 608 + starting));

        InnerProductVerifier.InnerProductProof memory ipProof;
        ipProof.ls = new Utils.G1Point[](6);
        ipProof.rs = new Utils.G1Point[](6);
        for (uint256 i = 0; i < 6; i++) { // 2^6 = 64.
            ipProof.ls[i] = Utils.G1Point(Utils.slice(arr, 640 + starting + i * 64), Utils.slice(arr, 672 + starting + i * 64));
            ipProof.rs[i] = Utils.G1Point(Utils.slice(arr, 640 + starting + (6 + i) * 64), Utils.slice(arr, 672 + starting + (6 + i) * 64));
        }
        ipProof.a = uint256(Utils.slice(arr, 640 + starting + 6 * 128));
        ipProof.b = uint256(Utils.slice(arr, 672 + starting + 6 * 128));
        proof.ipProof = ipProof;

        return proof;
    }
}

File 10 of 10: Utils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

library Utils {

    uint256 constant GROUP_ORDER = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;
    uint256 constant FIELD_ORDER = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;

    function gAdd(uint256 x, uint256 y) internal pure returns (uint256) {
        return addmod(x, y, GROUP_ORDER);
    }

    function gMul(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulmod(x, y, GROUP_ORDER);
    }

    function gInv(uint256 x) internal view returns (uint256) {
        return gExp(x, GROUP_ORDER - 2);
    }

    function gMod(uint256 x) internal pure returns (uint256) {
        return x % GROUP_ORDER;
    }

    function gSub(uint256 x, uint256 y) internal pure returns (uint256) {
        return x >= y ? x - y : GROUP_ORDER - y + x;
    }

    function gNeg(uint256 x) internal pure returns (uint256) {
        return GROUP_ORDER - x;
    }

    function gExp(uint256 base, uint256 exponent) internal view returns (uint256 output) {
        uint256 order = GROUP_ORDER;
        assembly {
            let m := mload(0x40)
            mstore(m, 0x20)
            mstore(add(m, 0x20), 0x20)
            mstore(add(m, 0x40), 0x20)
            mstore(add(m, 0x60), base)
            mstore(add(m, 0x80), exponent)
            mstore(add(m, 0xa0), order)
            if iszero(staticcall(gas(), 0x05, m, 0xc0, m, 0x20)) { // staticcall or call?
                revert(0, 0)
            }
            output := mload(m)
        }
    }

    function fieldExp(uint256 base, uint256 exponent) internal view returns (uint256 output) { // warning: mod p, not q
        uint256 order = FIELD_ORDER;
        assembly {
            let m := mload(0x40)
            mstore(m, 0x20)
            mstore(add(m, 0x20), 0x20)
            mstore(add(m, 0x40), 0x20)
            mstore(add(m, 0x60), base)
            mstore(add(m, 0x80), exponent)
            mstore(add(m, 0xa0), order)
            if iszero(staticcall(gas(), 0x05, m, 0xc0, m, 0x20)) { // staticcall or call?
                revert(0, 0)
            }
            output := mload(m)
        }
    }

    struct G1Point {
        bytes32 x;
        bytes32 y;
    }

    function pAdd(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {
        assembly {
            let m := mload(0x40)
            mstore(m, mload(p1))
            mstore(add(m, 0x20), mload(add(p1, 0x20)))
            mstore(add(m, 0x40), mload(p2))
            mstore(add(m, 0x60), mload(add(p2, 0x20)))
            // Address of the desired EC ADD instruction: 0x06
            // Reference: https://eips.ethereum.org/EIPS/eip-196#implementation
            if iszero(staticcall(gas(), 0x06, m, 0x80, r, 0x40)) {
                revert(0, 0)
            }
        }
    }

    function pMul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) {
        assembly {
            let m := mload(0x40)
            mstore(m, mload(p))
            mstore(add(m, 0x20), mload(add(p, 0x20)))
            mstore(add(m, 0x40), s)
            // Address of the desired EC MUL instruction: 0x07
            // Reference: https://eips.ethereum.org/EIPS/eip-196#implementation
            if iszero(staticcall(gas(), 0x07, m, 0x60, r, 0x40)) {
                revert(0, 0)
            }
        }
    }

    function pNeg(G1Point memory p) internal pure returns (G1Point memory) {
        return G1Point(p.x, bytes32(FIELD_ORDER - uint256(p.y))); // p.y should already be reduced mod P?
    }

    function pEqual(G1Point memory p1, G1Point memory p2) internal pure returns (bool) {
        return p1.x == p2.x && p1.y == p2.y;
    }

    function g() internal pure returns (G1Point memory) {
        return G1Point(0x077da99d806abd13c9f15ece5398525119d11e11e9836b2ee7d23f6159ad87d4, 0x01485efa927f2ad41bff567eec88f32fb0a0f706588b4e41a8d587d008b7f875);
    }

    function h() internal pure returns (G1Point memory) {
        return G1Point(0x01b7de3dcf359928dd19f643d54dc487478b68a5b2634f9f1903c9fb78331aef, 0x2bda7d3ae6a557c716477c108be0d0f94abc6c4dc6b1bd93caccbcceaaa71d6b);
    }

    function mapInto(uint256 seed) internal view returns (G1Point memory) {
        uint256 y;
        while (true) {
            uint256 ySquared = fieldExp(seed, 3) + 3; // addmod instead of add: waste of gas, plus function overhead cost
            y = fieldExp(ySquared, (FIELD_ORDER + 1) / 4);
            if (fieldExp(y, 2) == ySquared) {
                break;
            }
            seed += 1;
        }
        return G1Point(bytes32(seed), bytes32(y));
    }

    function mapInto(string memory input) internal view returns (G1Point memory) {
        return mapInto(uint256(keccak256(abi.encodePacked(input))) % FIELD_ORDER);
    }

    function mapInto(string memory input, uint256 i) internal view returns (G1Point memory) {
        return mapInto(uint256(keccak256(abi.encodePacked(input, i))) % FIELD_ORDER);
    }

    function slice(bytes memory input, uint256 start) internal pure returns (bytes32 result) {
        assembly {
            let m := mload(0x40)
            mstore(m, mload(add(add(input, 0x20), start))) // why only 0x20?
            result := mload(m)
        }
    }

    function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
        if (_i == 0) {
            return "0";
        }
        uint j = _i;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len - 1;
        while (_i != 0) {
            bstr[k--] = byte(uint8(48 + _i % 10));
            _i /= 10;
        }
        return string(bstr);
    }
}


Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_transfer","type":"address"},{"internalType":"address","name":"_burn","type":"address"},{"internalType":"uint256","name":"_unit","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"label","type":"string"},{"indexed":true,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogUint256","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"indexed":false,"internalType":"struct Utils.G1Point[]","name":"parties","type":"tuple[]"}],"name":"TransferOccurred","type":"event"},{"inputs":[],"name":"BURN_FEE_DIVIDEND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BURN_FEE_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSFER_FEE_DIVIDEND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSFER_FEE_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"y","type":"tuple"},{"internalType":"uint256","name":"unitAmount","type":"uint256"},{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"u","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"bytes","name":"encGuess","type":"bytes"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epochBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"y","type":"tuple"},{"internalType":"uint256","name":"unitAmount","type":"uint256"},{"internalType":"bytes","name":"encGuess","type":"bytes"}],"name":"fund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"y","type":"tuple"}],"name":"getAccountState","outputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point[2]","name":"y_available","type":"tuple[2]"},{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point[2]","name":"y_pending","type":"tuple[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point[]","name":"y","type":"tuple[]"},{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"getBalance","outputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point[2][]","name":"accounts","type":"tuple[2][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"y","type":"tuple"}],"name":"getGuess","outputs":[{"internalType":"bytes","name":"y_guess","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastGlobalUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"lastRollOver","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"y","type":"tuple"},{"internalType":"uint256","name":"c","type":"uint256"},{"internalType":"uint256","name":"s","type":"uint256"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"yHash","type":"bytes32"}],"name":"registered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"multiplier","type":"uint256"},{"internalType":"uint256","name":"dividend","type":"uint256"}],"name":"setBurnFeeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_epochBase","type":"uint256"}],"name":"setEpochBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_epochLength","type":"uint256"}],"name":"setEpochLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_suterAgency","type":"address"}],"name":"setSuterAgency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"multiplier","type":"uint256"},{"internalType":"uint256","name":"dividend","type":"uint256"}],"name":"setTransferFeeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unit","type":"uint256"}],"name":"setUnit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"suterAgency","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurnFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFundCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTransferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUsers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point[]","name":"C","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"D","type":"tuple"},{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point[]","name":"y","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct Utils.G1Point","name":"u","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"transfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"unit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405260018055606460025560016003556005600455601860075560006008556000600a556000600b556000600c556000600d556000600e556000600f5560006014553480156200005157600080fd5b506040516200446a3803806200446a8339818101604052810190620000779190620001bf565b828282336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060098190555050505083601660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050506200029d565b600081519050620001a28162000269565b92915050565b600081519050620001b98162000283565b92915050565b60008060008060808587031215620001d657600080fd5b6000620001e68782880162000191565b9450506020620001f98782880162000191565b93505060406200020c8782880162000191565b92505060606200021f87828801620001a8565b91505092959194509250565b600062000238826200023f565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000274816200022b565b81146200028057600080fd5b50565b6200028e816200025f565b81146200029a57600080fd5b50565b6141bd80620002ad6000396000f3fe6080604052600436106101d85760003560e01c806395e9524811610102578063bc939a4711610095578063de3d3d0811610064578063de3d3d08146106b3578063e708278f146106de578063eff4d17814610707578063f9a5375b14610723576101d8565b8063bc939a4714610609578063bff1f9e114610634578063c3b6dcdc1461065f578063d49d518114610688576101d8565b8063aae07890116100d1578063aae078901461054d578063ad7a672f14610576578063ae364d8f146105a1578063b1537596146105cc576101d8565b806395e952481461047e5780639b0d85d3146104a9578063a568ce51146104d2578063a9b05a5614610510576101d8565b806357d775f81161017a5780637d84839c116101495780637d84839c146103d25780637d882097146103fd578063840cd74c14610428578063907af6c014610453576101d8565b806357d775f8146103285780635a6fcd40146103535780637207f20e1461037e5780637601a39e146103a7576101d8565b806327d084e7116101b657806327d084e71461025a578063324db30f1461029757806354eea796146102c25780635524d548146102eb576101d8565b8063042ed32a146101dd5780630e2249321461020657806318131f6a14610231575b600080fd5b3480156101e957600080fd5b5061020460048036038101906101ff9190612eb5565b61074c565b005b34801561021257600080fd5b5061021b61085a565b6040516102289190613ecb565b60405180910390f35b34801561023d57600080fd5b506102586004803603810190610253919061303b565b610860565b005b34801561026657600080fd5b50610281600480360381019061027c9190612de6565b610900565b60405161028e9190613a4a565b60405180910390f35b3480156102a357600080fd5b506102ac610bad565b6040516102b99190613ecb565b60405180910390f35b3480156102ce57600080fd5b506102e960048036038101906102e49190613012565b610bb3565b005b3480156102f757600080fd5b50610312600480360381019061030d9190612e63565b610c4b565b60405161031f9190613b5a565b60405180910390f35b34801561033457600080fd5b5061033d610e59565b60405161034a9190613ecb565b60405180910390f35b34801561035f57600080fd5b50610368610e5f565b6040516103759190613ecb565b60405180910390f35b34801561038a57600080fd5b506103a560048036038101906103a0919061303b565b610e65565b005b3480156103b357600080fd5b506103bc610f05565b6040516103c99190613ecb565b60405180910390f35b3480156103de57600080fd5b506103e7610f0b565b6040516103f49190613ecb565b60405180910390f35b34801561040957600080fd5b50610412610f11565b60405161041f9190613ecb565b60405180910390f35b34801561043457600080fd5b5061043d610f17565b60405161044a9190613ecb565b60405180910390f35b34801561045f57600080fd5b50610468610f1d565b6040516104759190613ecb565b60405180910390f35b34801561048a57600080fd5b50610493610f23565b6040516104a09190613ecb565b60405180910390f35b3480156104b557600080fd5b506104d060048036038101906104cb9190612fc3565b610f29565b005b3480156104de57600080fd5b506104f960048036038101906104f49190612e8c565b6110fa565b604051610507929190613a6c565b60405180910390f35b34801561051c57600080fd5b5061053760048036038101906105329190612e8c565b611213565b6040516105449190613b75565b60405180910390f35b34801561055957600080fd5b50610574600480360381019061056f9190613012565b6112f4565b005b34801561058257600080fd5b5061058b61138c565b6040516105989190613ecb565b60405180910390f35b3480156105ad57600080fd5b506105b6611392565b6040516105c39190613ecb565b60405180910390f35b3480156105d857600080fd5b506105f360048036038101906105ee9190612e63565b611398565b6040516106009190613ecb565b60405180910390f35b34801561061557600080fd5b5061061e6113b0565b60405161062b9190613998565b60405180910390f35b34801561064057600080fd5b506106496113d4565b6040516106569190613ecb565b60405180910390f35b34801561066b57600080fd5b5061068660048036038101906106819190612f1c565b6113da565b005b34801561069457600080fd5b5061069d611624565b6040516106aa9190613ecb565b60405180910390f35b3480156106bf57600080fd5b506106c861162c565b6040516106d59190613ecb565b60405180910390f35b3480156106ea57600080fd5b5061070560048036038101906107009190613012565b611632565b005b610721600480360381019061071c9190612d27565b6116ca565b005b34801561072f57600080fd5b5061074a60048036038101906107459190612cfe565b611dd6565b005b610757838383611ea7565b600061076283612093565b9050601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b81526004016107c3939291906139b3565b602060405180830381600087803b1580156107dd57600080fd5b505af11580156107f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108159190612e3a565b610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084b90613d97565b60405180910390fd5b50505050565b600d5481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e590613dd7565b60405180910390fd5b81600181905550806002819055505050565b60606000835190508067ffffffffffffffff8111801561091f57600080fd5b5060405190808252806020026020018201604052801561095957816020015b610946612a07565b81526020019060019003908161093e5790505b50915060005b81811015610ba557600085828151811061097557fe5b602002602001015160405160200161098d9190613e37565b60405160208183030381529060405280519060200120905060106000828152602001908152602001600020600280602002604051908101604052809291906000905b82821015610a0b5783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906109cf565b50505050848381518110610a1b57fe5b60200260200101819052508460126000838152602001908152602001600020541015610b9757610a49612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b82821015610aaf578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610a73565b505050509050610afd81600060028110610ac557fe5b6020020151868581518110610ad657fe5b6020026020010151600060028110610aea57fe5b60200201516120f590919063ffffffff16565b858481518110610b0957fe5b6020026020010151600060028110610b1d57fe5b6020020181905250610b6d81600160028110610b3557fe5b6020020151868581518110610b4657fe5b6020026020010151600160028110610b5a57fe5b60200201516120f590919063ffffffff16565b858481518110610b7957fe5b6020026020010151600160028110610b8d57fe5b6020020181905250505b50808060010191505061095f565b505092915050565b600c5481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3890613c17565b60405180910390fd5b8060078190555050565b6000610c55612a34565b60405180604001604052806000801b81526020016000801b8152509050610c7a612a54565b604051806040016040528060106000878152602001908152602001600020600280602002604051908101604052809291906000905b82821015610ceb578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610caf565b50505050815260200160116000878152602001908152602001600020600280602002604051908101604052809291906000905b82821015610d5a578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610d1e565b505050508152509050610d988282600060028110610d7457fe5b6020020151600060028110610d8557fe5b602002015161213990919063ffffffff16565b8015610dd55750610dd48282600060028110610db057fe5b6020020151600160028110610dc157fe5b602002015161213990919063ffffffff16565b5b8015610e125750610e118282600160028110610ded57fe5b6020020151600060028110610dfe57fe5b602002015161213990919063ffffffff16565b5b8015610e4f5750610e4e8282600160028110610e2a57fe5b6020020151600160028110610e3b57fe5b602002015161213990919063ffffffff16565b5b1592505050919050565b60075481565b60145481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ef3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eea90613d37565b60405180910390fd5b81600381905550806004819055505050565b60045481565b60015481565b600e5481565b60025481565b60095481565b60035481565b610f31612a34565b610f77610f4f610f4085612161565b8661218d90919063ffffffff16565b610f6984610f5b6121c6565b61218d90919063ffffffff16565b6120f590919063ffffffff16565b90506000610fb1308684604051602001610f9393929190613a13565b6040516020818303038152906040528051906020012060001c61222e565b9050838114610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec90613cb7565b60405180910390fd5b6000856040516020016110089190613e37565b60405160208183030381529060405280519060200120905061102981610c4b565b15611069576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106090613bd7565b60405180910390fd5b856011600083815260200190815260200160002060006002811061108957fe5b6002020160008201518160000155602082015181600101559050506110ac6121c6565b601160008381526020019081526020016000206001600281106110cb57fe5b6002020160008201518160000155602082015181600101559050506001600b5401600b81905550505050505050565b611102612a07565b61110a612a07565b60008360405160200161111d9190613e37565b60405160208183030381529060405280519060200120905060106000828152602001908152602001600020600280602002604051908101604052809291906000905b8282101561119b57838260020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061115f565b50505050925060116000828152602001908152602001600020600280602002604051908101604052809291906000905b828210156112075783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906111cb565b50505050915050915091565b60606000826040516020016112289190613e37565b604051602081830303815290604052805190602001209050601560008281526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112e75780601f106112bc576101008083540402835291602001916112e7565b820191906000526020600020905b8154815290600101906020018083116112ca57829003601f168201915b5050505050915050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611382576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137990613cd7565b60405180910390fd5b8060098190555050565b600a5481565b600f5481565b60126020528060005260406000206000915090505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5481565b60006113e585612093565b905060006002546001548302816113f857fe5b0490506114088787878787612261565b600081111561152b57601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b815260040161148e9291906139ea565b602060405180830381600087803b1580156114a857600080fd5b505af11580156114bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e09190612e3a565b61151f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151690613d77565b60405180910390fd5b80600c5401600c819055505b601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338385036040518363ffffffff1660e01b815260040161158a9291906139ea565b602060405180830381600087803b1580156115a457600080fd5b505af11580156115b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115dc9190612e3a565b61161b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161290613c97565b60405180910390fd5b50505050505050565b63ffffffff81565b60085481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116b790613c57565b60405180910390fd5b8060088190555050565b60005a905060008451905060608167ffffffffffffffff811180156116ee57600080fd5b5060405190808252806020026020018201604052801561172857816020015b611715612a34565b81526020019060019003908161170d5790505b50905060608267ffffffffffffffff8111801561174457600080fd5b5060405190808252806020026020018201604052801561177e57816020015b61176b612a34565b8152602001906001900390816117635790505b509050828951146117c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117bb90613b97565b60405180910390fd5b60005b83811015611aa55760008882815181106117dd57fe5b60200260200101516040516020016117f59190613e37565b60405160208183030381529060405280519060200120905061181681610c4b565b611855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184c90613d57565b60405180910390fd5b61185e81612703565b611866612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b828210156118cc578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190611890565b5050505090506119098c84815181106118e157fe5b6020026020010151826000600281106118f657fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060006002811061192857fe5b6002020160008201518160000155602082015181600101559050506119678b8260016002811061195457fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060016002811061198657fe5b60020201600082015181600001556020820151816001015590505060106000838152602001908152602001600020600280602002604051908101604052809291906000905b82821015611a075783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906119cb565b505050509050611a448c8481518110611a1c57fe5b602002602001015182600060028110611a3157fe5b60200201516120f590919063ffffffff16565b858481518110611a5057fe5b6020026020010181905250611a7f8b82600160028110611a6c57fe5b60200201516120f590919063ffffffff16565b848481518110611a8b57fe5b6020026020010181905250505080806001019150506117c7565b50600086604051602001611ab99190613e37565b60405160208183030381529060405280519060200120905060005b601380549050811015611b48578160138281548110611aef57fe5b90600052602060002001541415611b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3290613c37565b60405180910390fd5b8080600101915050611ad4565b506013819080600181540180825580915050600190039060005260206000200160009091909190915055600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d2d5e70a84848d8d8d6014548e8e6040518963ffffffff1660e01b8152600401611bdd989796959493929190613ab8565b60206040518083038186803b158015611bf557600080fd5b505afa158015611c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2d9190612e3a565b611c6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6390613cf7565b60405180910390fd5b60005a8603905060003a600454600354840281611c8557fe5b040290506000811115611d485780341015611cd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ccc90613bf7565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d3b573d6000803e3d6000fd5b5080600d5401600d819055505b3373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051600060405180830381858888f19350505050158015611d90573d6000803e3d6000fd5b507f9b814ae8a45a4c40d4c60ffa92e0c4b76dec41407cb28b43df9daffa3685f9ac8a604051611dc09190613a96565b60405180910390a1505050505050505050505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5b90613bb7565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b63ffffffff8211158015611ec3575063ffffffff82600a540111155b611f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef990613c77565b60405180910390fd5b81600a6000828254019250508190555081600e600082825401925050819055506001600f60008282540192505081905550600083604051602001611f469190613e37565b604051602081830303815290604052805190602001209050611f6781610c4b565b611fa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f9d90613d57565b60405180910390fd5b611faf81612703565b611fb7612a34565b60116000838152602001908152602001600020600060028110611fd657fe5b600202016040518060400160405290816000820154815260200160018201548152505090506120276120188561200a6121c6565b61218d90919063ffffffff16565b826120f590919063ffffffff16565b9050806011600084815260200190815260200160002060006002811061204957fe5b6002020160008201518160000155602082015181600101559050508260156000848152602001908152602001600020908051906020019061208b929190612a81565b505050505050565b6000816000111580156120aa575063ffffffff8211155b6120e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e090613db7565b60405180910390fd5b60095482029050919050565b6120fd612a34565b6040518351815260208401516020820152825160408201526020830151606082015260408260808360065afa61213257600080fd5b5092915050565b600081600001518360000151148015612159575081602001518360200151145b905092915050565b6000817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001039050919050565b612195612a34565b604051835181526020840151602082015282604082015260408260608360075afa6121bf57600080fd5b5092915050565b6121ce612a34565b60405180604001604052807f077da99d806abd13c9f15ece5398525119d11e11e9836b2ee7d23f6159ad87d460001b81526020017f01485efa927f2ad41bff567eec88f32fb0a0f706588b4e41a8d587d008b7f87560001b815250905090565b60007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001828161225957fe5b069050919050565b83600a5410156122a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161229d90613d17565b60405180910390fd5b83600a600082825403925050819055506000856040516020016122c99190613e37565b6040516020818303038152906040528051906020012090506122ea81610c4b565b612329576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232090613d57565b60405180910390fd5b61233281612703565b61233a612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b828210156123a0578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612364565b5050505090506123eb6123cb6123b588612161565b6123bd6121c6565b61218d90919063ffffffff16565b826000600281106123d857fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060006002811061240a57fe5b60020201600082015181600001556020820151816001015590505060106000838152602001908152602001600020600280602002604051908101604052809291906000905b8282101561248b57838260020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061244f565b5050505090506124d66124b66124a088612161565b6124a86121c6565b61218d90919063ffffffff16565b826000600281106124c357fe5b60200201516120f590919063ffffffff16565b816000600281106124e357fe5b60200201819052506000856040516020016124fe9190613e37565b60405160208183030381529060405280519060200120905060005b60138054905081101561258d57816013828154811061253457fe5b90600052602060002001541415612580576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257790613c37565b60405180910390fd5b8080600101915050612519565b506013819080600181540180825580915050600190039060005260206000200160009091909190915055836015600085815260200190815260200160002090805190602001906125de929190612a81565b50600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391d16ac88360006002811061262a57fe5b60200201518460016002811061263c57fe5b60200201518b6014548b338c6040518863ffffffff1660e01b815260040161266a9796959493929190613e52565b60206040518083038186803b15801561268257600080fd5b505afa158015612696573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ba9190612e3a565b6126f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f090613df7565b60405180910390fd5b5050505050505050565b600080600854141561272257600754438161271a57fe5b04905061277c565b6001600854141561274057600754428161273857fe5b04905061277b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161277290613e17565b60405180910390fd5b5b80601260008481526020019081526020016000205410156129e35761279f612a54565b604051806040016040528060106000868152602001908152602001600020600280602002604051908101604052809291906000905b828210156128105783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906127d4565b50505050815260200160116000868152602001908152602001600020600280602002604051908101604052809291906000905b8282101561287f578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612843565b5050505081525090506128df8160016002811061289857fe5b60200201516000600281106128a957fe5b6020020151826000600281106128bb57fe5b60200201516000600281106128cc57fe5b60200201516120f590919063ffffffff16565b601060008581526020019081526020016000206000600281106128fe57fe5b6002020160008201518160000155602082015181600101559050506129708160016002811061292957fe5b602002015160016002811061293a57fe5b60200201518260006002811061294c57fe5b602002015160016002811061295d57fe5b60200201516120f590919063ffffffff16565b6010600085815260200190815260200160002060016002811061298f57fe5b6002020160008201518160000155602082015181600101559050506011600084815260200190815260200160002060006129c99190612b01565b816012600085815260200190815260200160002081905550505b806014541015612a03578060148190555060136000612a029190612b2c565b5b5050565b60405180604001604052806002905b612a1e612a34565b815260200190600190039081612a165790505090565b604051806040016040528060008019168152602001600080191681525090565b60405180604001604052806002905b612a6b612a07565b815260200190600190039081612a635790505090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612ac257805160ff1916838001178555612af0565b82800160010185558215612af0579182015b82811115612aef578251825591602001919060010190612ad4565b5b509050612afd9190612b4d565b5090565b5060008082016000905560018201600090555060020160008082016000905560018201600090555050565b5080546000825590600052602060002090810190612b4a9190612b6a565b50565b5b80821115612b66576000816000905550600101612b4e565b5090565b5b80821115612b83576000816000905550600101612b6b565b5090565b600081359050612b968161412b565b92915050565b600082601f830112612bad57600080fd5b8135612bc0612bbb82613f13565b613ee6565b91508181835260208401935060208101905083856040840282011115612be557600080fd5b60005b83811015612c155781612bfb8882612c9d565b845260208401935060408301925050600181019050612be8565b5050505092915050565b600081519050612c2e81614142565b92915050565b600081359050612c4381614159565b92915050565b600082601f830112612c5a57600080fd5b8135612c6d612c6882613f3b565b613ee6565b91508082526020830160208301858383011115612c8957600080fd5b612c948382846140d8565b50505092915050565b600060408284031215612caf57600080fd5b612cb96040613ee6565b90506000612cc984828501612c34565b6000830152506020612cdd84828501612c34565b60208301525092915050565b600081359050612cf881614170565b92915050565b600060208284031215612d1057600080fd5b6000612d1e84828501612b87565b91505092915050565b600080600080600060e08688031215612d3f57600080fd5b600086013567ffffffffffffffff811115612d5957600080fd5b612d6588828901612b9c565b9550506020612d7688828901612c9d565b945050606086013567ffffffffffffffff811115612d9357600080fd5b612d9f88828901612b9c565b9350506080612db088828901612c9d565b92505060c086013567ffffffffffffffff811115612dcd57600080fd5b612dd988828901612c49565b9150509295509295909350565b60008060408385031215612df957600080fd5b600083013567ffffffffffffffff811115612e1357600080fd5b612e1f85828601612b9c565b9250506020612e3085828601612ce9565b9150509250929050565b600060208284031215612e4c57600080fd5b6000612e5a84828501612c1f565b91505092915050565b600060208284031215612e7557600080fd5b6000612e8384828501612c34565b91505092915050565b600060408284031215612e9e57600080fd5b6000612eac84828501612c9d565b91505092915050565b600080600060808486031215612eca57600080fd5b6000612ed886828701612c9d565b9350506040612ee986828701612ce9565b925050606084013567ffffffffffffffff811115612f0657600080fd5b612f1286828701612c49565b9150509250925092565b600080600080600060e08688031215612f3457600080fd5b6000612f4288828901612c9d565b9550506040612f5388828901612ce9565b9450506060612f6488828901612c9d565b93505060a086013567ffffffffffffffff811115612f8157600080fd5b612f8d88828901612c49565b92505060c086013567ffffffffffffffff811115612faa57600080fd5b612fb688828901612c49565b9150509295509295909350565b600080600060808486031215612fd857600080fd5b6000612fe686828701612c9d565b9350506040612ff786828701612ce9565b925050606061300886828701612ce9565b9150509250925092565b60006020828403121561302457600080fd5b600061303284828501612ce9565b91505092915050565b6000806040838503121561304e57600080fd5b600061305c85828601612ce9565b925050602061306d85828601612ce9565b9150509250929050565b60006130838383613132565b60808301905092915050565b600061309b838361392b565b60408301905092915050565b6130b0816140a2565b82525050565b6130bf81614050565b82525050565b6130ce8161403e565b82525050565b60006130df82613f91565b6130e98185613fe4565b93506130f483613f67565b8060005b8381101561312557815161310c8882613077565b975061311783613fbd565b9250506001810190506130f8565b5085935050505092915050565b61313b81613f9c565b6131458184613ff5565b925061315082613f77565b8060005b83811015613181578151613168878261308f565b965061317383613fca565b925050600181019050613154565b505050505050565b61319281613f9c565b61319c8184614000565b92506131a782613f77565b8060005b838110156131d85781516131bf878261308f565b96506131ca83613fca565b9250506001810190506131ab565b505050505050565b60006131eb82613fa7565b6131f5818561400b565b935061320083613f81565b8060005b83811015613231578151613218888261308f565b975061322383613fd7565b925050600181019050613204565b5085935050505092915050565b61324781614062565b82525050565b6132568161406e565b82525050565b600061326782613fb2565b613271818561401c565b93506132818185602086016140e7565b61328a8161411a565b840191505092915050565b60006132a2601c8361402d565b91507f496e707574206172726179206c656e677468206d69736d6174636821000000006000830152602082019050919050565b60006132e260308361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765206167656e63792e000000000000000000000000000000006020830152604082019050919050565b6000613348601b8361402d565b91507f4163636f756e7420616c726561647920726567697374657265642100000000006000830152602082019050919050565b600061338860328361402d565b91507f4e6f7420656e6f756768206665652073656e742077697468207468652074726160008301527f6e73666572207472616e73616374696f6e2e00000000000000000000000000006020830152604082019050919050565b60006133ee60368361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e67652065706f6368206c656e6774682e000000000000000000006020830152604082019050919050565b600061345460138361402d565b91507f4e6f6e636520616c7265616479207365656e21000000000000000000000000006000830152602082019050919050565b600061349460348361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e67652065706f636820626173652e0000000000000000000000006020830152604082019050919050565b60006134fa60288361402d565b91507f46756e642070757368657320636f6e74726163742070617374206d6178696d7560008301527f6d2076616c75652e0000000000000000000000000000000000000000000000006020830152604082019050919050565b600061356060188361402d565b91507f4661696c20746f207472616e7366657220746f6b656e732e00000000000000006000830152602082019050919050565b60006135a0601f8361402d565b91507f496e76616c696420726567697374726174696f6e207369676e617475726521006000830152602082019050919050565b60006135e0602e8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e676520756e69742e0000000000000000000000000000000000006020830152604082019050919050565b600061364660238361402d565b91507f5472616e736665722070726f6f6620766572696669636174696f6e206661696c60008301527f65642100000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006136ac601c8361402d565b91507f4275726e206661696c73207468652073616e69747920636865636b2e000000006000830152602082019050919050565b60006136ec603f8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765207472616e73666572206665652073747261746567792e006020830152604082019050919050565b6000613752601b8361402d565b91507f4163636f756e74206e6f742079657420726567697374657265642e00000000006000830152602082019050919050565b600061379260138361402d565b91507f4661696c20746f20636861726765206665652e000000000000000000000000006000830152602082019050919050565b60006137d2601d8361402d565b91507f4e617469766520277472616e7366657246726f6d27206661696c65642e0000006000830152602082019050919050565b600061381260138361402d565b91507f416d6f756e74206f7574206f662072616e6765000000000000000000000000006000830152602082019050919050565b6000613852603b8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765206275726e206665652073747261746567792e00000000006020830152604082019050919050565b60006138b8601f8361402d565b91507f4275726e2070726f6f6620766572696669636174696f6e206661696c656421006000830152602082019050919050565b60006138f860138361402d565b91507f496e76616c69642065706f636820626173652e000000000000000000000000006000830152602082019050919050565b604082016000820151613941600085018261324d565b506020820151613954602085018261324d565b50505050565b604082016000820151613970600085018261324d565b506020820151613983602085018261324d565b50505050565b61399281614098565b82525050565b60006020820190506139ad60008301846130b6565b92915050565b60006060820190506139c860008301866130a7565b6139d560208301856130c5565b6139e26040830184613989565b949350505050565b60006040820190506139ff60008301856130a7565b613a0c6020830184613989565b9392505050565b600060a082019050613a2860008301866130c5565b613a35602083018561395a565b613a42606083018461395a565b949350505050565b60006020820190508181036000830152613a6481846130d4565b905092915050565b600061010082019050613a826000830185613189565b613a8f6080830184613189565b9392505050565b60006020820190508181036000830152613ab081846131e0565b905092915050565b6000610140820190508181036000830152613ad3818b6131e0565b90508181036020830152613ae7818a6131e0565b90508181036040830152613afb81896131e0565b9050613b0a606083018861395a565b81810360a0830152613b1c81876131e0565b9050613b2b60c0830186613989565b613b3860e083018561395a565b818103610120830152613b4b818461325c565b90509998505050505050505050565b6000602082019050613b6f600083018461323e565b92915050565b60006020820190508181036000830152613b8f818461325c565b905092915050565b60006020820190508181036000830152613bb081613295565b9050919050565b60006020820190508181036000830152613bd0816132d5565b9050919050565b60006020820190508181036000830152613bf08161333b565b9050919050565b60006020820190508181036000830152613c108161337b565b9050919050565b60006020820190508181036000830152613c30816133e1565b9050919050565b60006020820190508181036000830152613c5081613447565b9050919050565b60006020820190508181036000830152613c7081613487565b9050919050565b60006020820190508181036000830152613c90816134ed565b9050919050565b60006020820190508181036000830152613cb081613553565b9050919050565b60006020820190508181036000830152613cd081613593565b9050919050565b60006020820190508181036000830152613cf0816135d3565b9050919050565b60006020820190508181036000830152613d1081613639565b9050919050565b60006020820190508181036000830152613d308161369f565b9050919050565b60006020820190508181036000830152613d50816136df565b9050919050565b60006020820190508181036000830152613d7081613745565b9050919050565b60006020820190508181036000830152613d9081613785565b9050919050565b60006020820190508181036000830152613db0816137c5565b9050919050565b60006020820190508181036000830152613dd081613805565b9050919050565b60006020820190508181036000830152613df081613845565b9050919050565b60006020820190508181036000830152613e10816138ab565b9050919050565b60006020820190508181036000830152613e30816138eb565b9050919050565b6000604082019050613e4c600083018461395a565b92915050565b600061016082019050613e68600083018a61395a565b613e75604083018961395a565b613e82608083018861395a565b613e8f60c0830187613989565b613e9c60e083018661395a565b613eaa6101208301856130a7565b818103610140830152613ebd818461325c565b905098975050505050505050565b6000602082019050613ee06000830184613989565b92915050565b6000604051905081810181811067ffffffffffffffff82111715613f0957600080fd5b8060405250919050565b600067ffffffffffffffff821115613f2a57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115613f5257600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050919050565b6000819050602082019050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600061404982614078565b9050919050565b600061405b82614078565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006140ad826140b4565b9050919050565b60006140bf826140c6565b9050919050565b60006140d182614078565b9050919050565b82818337600083830152505050565b60005b838110156141055780820151818401526020810190506140ea565b83811115614114576000848401525b50505050565b6000601f19601f8301169050919050565b61413481614050565b811461413f57600080fd5b50565b61414b81614062565b811461415657600080fd5b50565b6141628161406e565b811461416d57600080fd5b50565b61417981614098565b811461418457600080fd5b5056fea2646970667358221220321c1bcb54c741f2a54dca27ed414b60293c46ce2739846ee509024cae256e3a64736f6c634300060c0033000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d56000000000000000000000000076010bfc6377b24d10545e69840c9a6b79d6471000000000000000000000000d3a56c7fd5493268d299a4111a1b493c95b0b5690000000000000000000000000000000000000000000000000de0b6b3a7640000

Deployed ByteCode Sourcemap

163:1589:7:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;732:429;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1353:35:6;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4350:267;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8406:835;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1316:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5859:199;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7881:337;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;783:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1785:35;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5375:283;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;570:40;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;399:38;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1394:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;443:38;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1076:19;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;522:42;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6440:1435;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9247:311;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;9564:199;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6064:163;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1244:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1432:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1630:47;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;267:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1281:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1167:583:7;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1200:37:6;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;821:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5664:189;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;12599:1959;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6233:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;732:429:7;830:33;839:1;842:10;854:8;830;:33::i;:::-;874:20;897:26;912:10;897:14;:26::i;:::-;874:49;;1061:5;;;;;;;;;;;:18;;;1080:10;1100:4;1107:12;1061:59;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1053:101;;;;;;;;;;;;:::i;:::-;;;;;;;;;732:429;;;;:::o;1353:35:6:-;;;;:::o;4350:267::-;4455:11;;;;;;;;;;4441:25;;:10;:25;;;4433:97;;;;;;;;;;;;:::i;:::-;;;;;;;;;4562:10;4540:19;:32;;;;4602:8;4582:17;:28;;;;4350:267;;:::o;8406:835::-;8488:34;8753:12;8768:1;:8;8753:23;;8820:4;8797:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;8786:39;;8840:9;8835:400;8859:4;8855:1;:8;8835:400;;;8884:13;8921:1;8923;8921:4;;;;;;;;;;;;;;8910:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;8900:27;;;;;;8884:43;;8955:3;:10;8959:5;8955:10;;;;;;;;;;;8941:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:8;8950:1;8941:11;;;;;;;;;;;;;:24;;;;9005:5;8983:12;:19;8996:5;8983:19;;;;;;;;;;;;:27;8979:246;;;9030:31;;:::i;:::-;9064:7;:14;9072:5;9064:14;;;;;;;;;;;9030:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9113:31;9133:7;9141:1;9133:10;;;;;;;;;;;9113:8;9122:1;9113:11;;;;;;;;;;;;;;9125:1;9113:14;;;;;;;;;;;:19;;:31;;;;:::i;:::-;9096:8;9105:1;9096:11;;;;;;;;;;;;;;9108:1;9096:14;;;;;;;;;;:48;;;;9179:31;9199:7;9207:1;9199:10;;;;;;;;;;;9179:8;9188:1;9179:11;;;;;;;;;;;;;;9191:1;9179:14;;;;;;;;;;;:19;;:31;;;;:::i;:::-;9162:8;9171:1;9162:11;;;;;;;;;;;;;;9174:1;9162:14;;;;;;;;;;:48;;;;8979:246;;8835:400;8865:3;;;;;;;8835:400;;;;8406:835;;;;;:::o;1316:31::-;;;;:::o;5859:199::-;5945:11;;;;;;;;;;5931:25;;:10;:25;;;5923:92;;;;;;;;;;;;:::i;:::-;;;;;;;;;6039:12;6025:11;:26;;;;5859:199;:::o;7881:337::-;7937:4;7953:25;;:::i;:::-;7981:19;;;;;;;;7995:1;7981:19;;;;;;7998:1;7981:19;;;;;7953:47;;8010:34;;:::i;:::-;:65;;;;;;;;8048:3;:10;8052:5;8048:10;;;;;;;;;;;8010:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8060:7;:14;8068:5;8060:14;;;;;;;;;;;8010:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8094:26;8115:4;8094:7;8102:1;8094:10;;;;;;;;;;;8105:1;8094:13;;;;;;;;;;;:20;;:26;;;;:::i;:::-;:56;;;;;8124:26;8145:4;8124:7;8132:1;8124:10;;;;;;;;;;;8135:1;8124:13;;;;;;;;;;;:20;;:26;;;;:::i;:::-;8094:56;:86;;;;;8154:26;8175:4;8154:7;8162:1;8154:10;;;;;;;;;;;8165:1;8154:13;;;;;;;;;;;:20;;:26;;;;:::i;:::-;8094:86;:116;;;;;8184:26;8205:4;8184:7;8192:1;8184:10;;;;;;;;;;;8195:1;8184:13;;;;;;;;;;;:20;;:26;;;;:::i;:::-;8094:116;8092:119;8085:126;;;;7881:337;;;:::o;783:31::-;;;;:::o;1785:35::-;;;;:::o;5375:283::-;5484:11;;;;;;;;;;5470:25;;:10;:25;;;5462:101;;;;;;;;;;;;:::i;:::-;;;;;;;;;5599:10;5573:23;:36;;;;5643:8;5619:21;:32;;;;5375:283;;:::o;570:40::-;;;;:::o;399:38::-;;;;:::o;1394:32::-;;;;:::o;443:38::-;;;;:::o;1076:19::-;;;;:::o;522:42::-;;;;:::o;6440:1435::-;6602:22;;:::i;:::-;6627:40;6650:16;6657:8;:1;:6;:8::i;:::-;6650:1;:6;;:16;;;;:::i;:::-;6627:17;6642:1;6627:9;:7;:9::i;:::-;:14;;:17;;;;:::i;:::-;:22;;:40;;;;:::i;:::-;6602:65;;6677:17;6697:58;6734:4;6741:1;6744;6715:31;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;6705:42;;;;;;6697:51;;:56;:58::i;:::-;6677:78;;6786:1;6773:9;:14;6765:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;6833:13;6870:1;6859:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;6849:24;;;;;;6833:40;;6892:17;6903:5;6892:10;:17::i;:::-;6891:18;6883:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;7790:1;7770:7;:14;7778:5;7770:14;;;;;;;;;;;7785:1;7770:17;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;;7821:9;:7;:9::i;:::-;7801:7;:14;7809:5;7801:14;;;;;;;;;;;7816:1;7801:17;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;;7867:1;7854:10;;:14;7841:10;:27;;;;6440:1435;;;;;;:::o;9247:311::-;9318:35;;:::i;:::-;9355:33;;:::i;:::-;9400:13;9437:1;9426:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;9416:24;;;;;;9400:40;;9464:3;:10;9468:5;9464:10;;;;;;;;;;;9450:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9496:7;:14;9504:5;9496:14;;;;;;;;;;;9484:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9520:31;9247:311;;;:::o;9564:199::-;9628:20;9660:13;9697:1;9686:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;9676:24;;;;;;9660:40;;9720:5;:12;9726:5;9720:12;;;;;;;;;;;9710:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9742:14;9564:199;;;:::o;6064:163::-;6136:11;;;;;;;;;;6122:25;;:10;:25;;;6114:84;;;;;;;;;;;;:::i;:::-;;;;;;;;;6215:5;6208:4;:12;;;;6064:163;:::o;1244:31::-;;;;:::o;1432:33::-;;;;:::o;1630:47::-;;;;;;;;;;;;;;;;;:::o;267:34::-;;;;;;;;;;;;:::o;1281:29::-;;;;:::o;1167:583:7:-;1309:20;1332:26;1347:10;1332:14;:26::i;:::-;1309:49;;1368:11;1419:17;;1397:19;;1382:12;:34;:54;;;;;;1368:68;;1448:43;1457:1;1460:10;1472:1;1475:5;1482:8;1448;:43::i;:::-;1512:1;1506:3;:7;1502:149;;;1537:5;;;;;;;;;;;:14;;;1552:11;;;;;;;;;;1565:3;1537:32;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1529:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;1637:3;1622:12;;:18;1607:12;:33;;;;1502:149;1668:5;;;;;;;;;;;:14;;;1683:10;1710:3;1695:12;:18;1668:46;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1660:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;1167:583;;;;;;;:::o;1200:37:6:-;1230:7;1200:37;:::o;821:28::-;;;;:::o;5664:189::-;5746:11;;;;;;;;;;5732:25;;:10;:25;;;5724:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;5836:10;5824:9;:22;;;;5664:189;:::o;12599:1959::-;12809:16;12828:9;12809:28;;12917:12;12932:1;:8;12917:23;;12950:26;12999:4;12979:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;12950:54;;13014:26;13063:4;13043:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;13014:54;;13098:4;13086:1;:8;:16;13078:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;13152:9;13147:599;13171:4;13167:1;:8;13147:599;;;13196:13;13233:1;13235;13233:4;;;;;;;;;;;;;;13222:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;13212:27;;;;;;13196:43;;13261:17;13272:5;13261:10;:17::i;:::-;13253:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;13324:15;13333:5;13324:8;:15::i;:::-;13353:31;;:::i;:::-;13387:7;:14;13395:5;13387:14;;;;;;;;;;;13353:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13435:21;13451:1;13453;13451:4;;;;;;;;;;;;;;13435:7;13443:1;13435:10;;;;;;;;;;;:15;;:21;;;;:::i;:::-;13415:7;:14;13423:5;13415:14;;;;;;;;;;;13430:1;13415:17;;;;;;;;;;:41;;;;;;;;;;;;;;;;;;;13490:18;13506:1;13490:7;13498:1;13490:10;;;;;;;;;;;:15;;:18;;;;:::i;:::-;13470:7;:14;13478:5;13470:14;;;;;;;;;;;13485:1;13470:17;;;;;;;;;;:38;;;;;;;;;;;;;;;;;;;13640:3;:10;13644:5;13640:10;;;;;;;;;;;13630:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13673:21;13689:1;13691;13689:4;;;;;;;;;;;;;;13673:7;13681:1;13673:10;;;;;;;;;;;:15;;:21;;;;:::i;:::-;13664:3;13668:1;13664:6;;;;;;;;;;;;;:30;;;;13717:18;13733:1;13717:7;13725:1;13717:10;;;;;;;;;;;:15;;:18;;;;:::i;:::-;13708:3;13712:1;13708:6;;;;;;;;;;;;;:27;;;;13147:599;;13177:3;;;;;;;13147:599;;;;13756:13;13793:1;13782:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;13772:24;;;;;;13756:40;;13811:9;13806:123;13830:8;:15;;;;13826:1;:19;13806:123;;;13889:5;13874:8;13883:1;13874:11;;;;;;;;;;;;;;;;:20;;13866:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;13847:3;;;;;;;13806:123;;;;13938:8;13952:5;13938:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13977:16;;;;;;;;;;;:31;;;14009:3;14014;14019:1;14022;14025;14028:16;;14046:1;14049:5;13977:78;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13969:126;;;;;;;;;;;;:::i;:::-;;;;;;;;;14106:15;14135:9;14124:8;:20;14106:38;;14163:11;14239;14214:21;;14188:23;;14178:7;:33;:57;;;;;;14177:73;14163:87;;14270:1;14264:3;:7;14260:211;;;14308:3;14295:9;:16;;14287:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;14380:11;;;;;;;;;;:20;;:25;14401:3;14380:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14457:3;14438:16;;:22;14419:16;:41;;;;14260:211;14480:10;:19;;:36;14512:3;14500:9;:15;14480:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14532:19;14549:1;14532:19;;;;;;:::i;:::-;;;;;;;;12599:1959;;;;;;;;;;;;:::o;6233:201::-;6327:11;;;;;;;;;;6313:25;;:10;:25;;;6305:86;;;;;;;;;;;;:::i;:::-;;;;;;;;;6415:12;6401:11;;:26;;;;;;;;;;;;;;;;;;6233:201;:::o;10708:629::-;1230:7;10817:6;:13;;:45;;;;;1230:7;10849:6;10834:12;;:21;:28;;10817:45;10809:98;;;;;;;;;;;;:::i;:::-;;;;;;;;;10933:6;10917:12;;:22;;;;;;;;;;;10966:6;10949:13;;:23;;;;;;;;;;;11000:1;10982:14;;:19;;;;;;;;;;;11012:13;11049:1;11038:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;11028:24;;;;;;11012:40;;11070:17;11081:5;11070:10;:17::i;:::-;11062:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;11129:15;11138:5;11129:8;:15::i;:::-;11155:28;;:::i;:::-;11186:7;:14;11194:5;11186:14;;;;;;;;;;;11201:1;11186:17;;;;;;;;;;11155:48;;;;;;;;;;;;;;;;;;;;;;;;;;;11223:36;11236:22;11251:6;11236:9;:7;:9::i;:::-;:14;;:22;;;;:::i;:::-;11223:7;:12;;:36;;;;:::i;:::-;11213:46;;11289:7;11269;:14;11277:5;11269:14;;;;;;;;;;;11284:1;11269:17;;;;;;;;;;:27;;;;;;;;;;;;;;;;;;;11322:8;11307:5;:12;11313:5;11307:12;;;;;;;;;;;:23;;;;;;;;;;;;:::i;:::-;;10708:629;;;;;:::o;3228:195::-;3295:7;3327:10;3322:1;:15;;:36;;;;;1230:7;3341:10;:17;;3322:36;3314:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;3412:4;;3399:10;:17;3392:24;;3228:195;;;:::o;2287:602:9:-;2362:16;;:::i;:::-;2428:4;2422:11;2462:2;2456:9;2453:1;2446:20;2514:4;2510:2;2506:13;2500:20;2493:4;2490:1;2486:12;2479:42;2561:2;2555:9;2548:4;2545:1;2541:12;2534:31;2613:4;2609:2;2605:13;2599:20;2592:4;2589:1;2585:12;2578:42;2822:4;2819:1;2813:4;2810:1;2804:4;2797:5;2786:41;2776:2;;2857:1;2854;2847:12;2776:2;2399:484;;;;;:::o;3619:135::-;3696:4;3727:2;:4;;;3719:2;:4;;;:12;:28;;;;;3743:2;:4;;;3735:2;:4;;;:12;3719:28;3712:35;;3619:135;;;;:::o;912:96::-;960:7;1000:1;143:66;986:15;979:22;;912:96;;;:::o;2895:528::-;2961:16;;:::i;:::-;3027:4;3021:11;3061:1;3055:8;3052:1;3045:19;3111:4;3108:1;3104:12;3098:19;3091:4;3088:1;3084:12;3077:41;3152:1;3145:4;3142:1;3138:12;3131:23;3356:4;3353:1;3347:4;3344:1;3338:4;3331:5;3320:41;3310:2;;3391:1;3388;3381:12;3310:2;2998:419;;;;;:::o;3760:219::-;3796:14;;:::i;:::-;3829:143;;;;;;;;3837:66;3829:143;;;;;;3905:66;3829:143;;;;;3822:150;;3760:219;:::o;676:96::-;724:7;143:66;750:1;:15;;;;;;743:22;;676:96;;;:::o;11343:1250:6:-;11621:6;11605:12;;:22;;11597:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;11686:6;11670:12;;:22;;;;;;;;;;;11712:13;11749:1;11738:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;11728:24;;;;;;11712:40;;11770:17;11781:5;11770:10;:17::i;:::-;11762:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;11829:15;11838:5;11829:8;:15::i;:::-;11855:31;;:::i;:::-;11889:7;:14;11897:5;11889:14;;;;;;;;;;;11855:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11933:46;11949:29;11964:13;:6;:11;:13::i;:::-;11949:9;:7;:9::i;:::-;:14;;:29;;;;:::i;:::-;11933:7;11941:1;11933:10;;;;;;;;;;;:15;;:46;;;;:::i;:::-;11913:7;:14;11921:5;11913:14;;;;;;;;;;;11928:1;11913:17;;;;;;;;;;:66;;;;;;;;;;;;;;;;;;;12000:3;:10;12004:5;12000:10;;;;;;;;;;;11990:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12107:46;12123:29;12138:13;:6;:11;:13::i;:::-;12123:9;:7;:9::i;:::-;:14;;:29;;;;:::i;:::-;12107:7;12115:1;12107:10;;;;;;;;;;;:15;;:46;;;;:::i;:::-;12094:7;12102:1;12094:10;;;;;;;;;;:59;;;;12163:13;12200:1;12189:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;12179:24;;;;;;12163:40;;12218:9;12213:123;12237:8;:15;;;;12233:1;:19;12213:123;;;12296:5;12281:8;12290:1;12281:11;;;;;;;;;;;;;;;;:20;;12273:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;12254:3;;;;;;;12213:123;;;;12345:8;12359:5;12345:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12391:8;12376:5;:12;12382:5;12376:12;;;;;;;;;;;:23;;;;;;;;;;;;:::i;:::-;;12418:12;;;;;;;;;;;:23;;;12442:7;12450:1;12442:10;;;;;;;;;;;12454:7;12462:1;12454:10;;;;;;;;;;;12466:1;12469:16;;12487:1;12490:10;12502:5;12418:90;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12410:134;;;;;;;;;;;;:::i;:::-;;;;;;;;;11343:1250;;;;;;;;:::o;9769:933::-;9821:9;9861:1;9848:9;;:14;9844:198;;;9895:11;;9880:12;:26;;;;;;9876:30;;9844:198;;;9938:1;9925:9;;:14;9921:121;;;9975:11;;9957:15;:29;;;;;;9953:33;;9921:121;;;10013:29;;;;;;;;;;:::i;:::-;;;;;;;;9921:121;9844:198;10079:1;10057:12;:19;10070:5;10057:19;;;;;;;;;;;;:23;10053:534;;;10096:34;;:::i;:::-;:65;;;;;;;;10134:3;:10;10138:5;10134:10;;;;;;;;;;;10096:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10146:7;:14;10154:5;10146:14;;;;;;;;;;;10096:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10191:33;10210:7;10218:1;10210:10;;;;;;;;;;;10221:1;10210:13;;;;;;;;;;;10191:7;10199:1;10191:10;;;;;;;;;;;10202:1;10191:13;;;;;;;;;;;:18;;:33;;;;:::i;:::-;10175:3;:10;10179:5;10175:10;;;;;;;;;;;10186:1;10175:13;;;;;;;;;;:49;;;;;;;;;;;;;;;;;;;10254:33;10273:7;10281:1;10273:10;;;;;;;;;;;10284:1;10273:13;;;;;;;;;;;10254:7;10262:1;10254:10;;;;;;;;;;;10265:1;10254:13;;;;;;;;;;;:18;;:33;;;;:::i;:::-;10238:3;:10;10242:5;10238:10;;;;;;;;;;;10249:1;10238:13;;;;;;;;;;:49;;;;;;;;;;;;;;;;;;;10461:7;:14;10469:5;10461:14;;;;;;;;;;;;10454:21;;;;:::i;:::-;10575:1;10553:12;:19;10566:5;10553:19;;;;;;;;;;;:23;;;;10053:534;;10619:1;10600:16;;:20;10596:100;;;10655:1;10636:16;:20;;;;10677:8;;10670:15;;;;:::i;:::-;10596:100;9769:933;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;5:146::-;;93:6;80:20;71:29;;105:41;140:5;105:41;:::i;:::-;65:86;;;;:::o;189:782::-;;331:3;324:4;316:6;312:17;308:27;298:2;;349:1;346;339:12;298:2;386:6;373:20;408:105;423:89;505:6;423:89;:::i;:::-;408:105;:::i;:::-;399:114;;530:5;555:6;548:5;541:21;585:4;577:6;573:17;563:27;;607:4;602:3;598:14;591:21;;660:6;707:3;699:4;691:6;687:17;682:3;678:27;675:36;672:2;;;724:1;721;714:12;672:2;749:1;734:231;759:6;756:1;753:13;734:231;;;817:3;839:62;897:3;885:10;839:62;:::i;:::-;834:3;827:75;925:4;920:3;916:14;909:21;;953:4;948:3;944:14;937:21;;791:174;781:1;778;774:9;769:14;;734:231;;;738:14;291:680;;;;;;;:::o;979:128::-;;1060:6;1054:13;1045:22;;1072:30;1096:5;1072:30;:::i;:::-;1039:68;;;;:::o;1114:130::-;;1194:6;1181:20;1172:29;;1206:33;1233:5;1206:33;:::i;:::-;1166:78;;;;:::o;1252:440::-;;1353:3;1346:4;1338:6;1334:17;1330:27;1320:2;;1371:1;1368;1361:12;1320:2;1408:6;1395:20;1430:64;1445:48;1486:6;1445:48;:::i;:::-;1430:64;:::i;:::-;1421:73;;1514:6;1507:5;1500:21;1550:4;1542:6;1538:17;1583:4;1576:5;1572:16;1618:3;1609:6;1604:3;1600:16;1597:25;1594:2;;;1635:1;1632;1625:12;1594:2;1645:41;1679:6;1674:3;1669;1645:41;:::i;:::-;1313:379;;;;;;;:::o;1727:461::-;;1841:4;1829:9;1824:3;1820:19;1816:30;1813:2;;;1859:1;1856;1849:12;1813:2;1877:20;1892:4;1877:20;:::i;:::-;1868:29;;1944:1;1976:49;2021:3;2012:6;2001:9;1997:22;1976:49;:::i;:::-;1969:4;1962:5;1958:16;1951:75;1907:130;2084:2;2117:49;2162:3;2153:6;2142:9;2138:22;2117:49;:::i;:::-;2110:4;2103:5;2099:16;2092:75;2047:131;1807:381;;;;:::o;2195:130::-;;2275:6;2262:20;2253:29;;2287:33;2314:5;2287:33;:::i;:::-;2247:78;;;;:::o;2332:257::-;;2444:2;2432:9;2423:7;2419:23;2415:32;2412:2;;;2460:1;2457;2450:12;2412:2;2495:1;2512:61;2565:7;2556:6;2545:9;2541:22;2512:61;:::i;:::-;2502:71;;2474:105;2406:183;;;;:::o;2596:1320::-;;;;;;2927:3;2915:9;2906:7;2902:23;2898:33;2895:2;;;2944:1;2941;2934:12;2895:2;3007:1;2996:9;2992:17;2979:31;3030:18;3022:6;3019:30;3016:2;;;3062:1;3059;3052:12;3016:2;3082:103;3177:7;3168:6;3157:9;3153:22;3082:103;:::i;:::-;3072:113;;2958:233;3222:2;3240:78;3310:7;3301:6;3290:9;3286:22;3240:78;:::i;:::-;3230:88;;3201:123;3383:2;3372:9;3368:18;3355:32;3407:18;3399:6;3396:30;3393:2;;;3439:1;3436;3429:12;3393:2;3459:103;3554:7;3545:6;3534:9;3530:22;3459:103;:::i;:::-;3449:113;;3334:234;3599:3;3618:78;3688:7;3679:6;3668:9;3664:22;3618:78;:::i;:::-;3608:88;;3578:124;3761:3;3750:9;3746:19;3733:33;3786:18;3778:6;3775:30;3772:2;;;3818:1;3815;3808:12;3772:2;3838:62;3892:7;3883:6;3872:9;3868:22;3838:62;:::i;:::-;3828:72;;3712:194;2889:1027;;;;;;;;:::o;3923:552::-;;;4094:2;4082:9;4073:7;4069:23;4065:32;4062:2;;;4110:1;4107;4100:12;4062:2;4173:1;4162:9;4158:17;4145:31;4196:18;4188:6;4185:30;4182:2;;;4228:1;4225;4218:12;4182:2;4248:103;4343:7;4334:6;4323:9;4319:22;4248:103;:::i;:::-;4238:113;;4124:233;4388:2;4406:53;4451:7;4442:6;4431:9;4427:22;4406:53;:::i;:::-;4396:63;;4367:98;4056:419;;;;;:::o;4482:257::-;;4594:2;4582:9;4573:7;4569:23;4565:32;4562:2;;;4610:1;4607;4600:12;4562:2;4645:1;4662:61;4715:7;4706:6;4695:9;4691:22;4662:61;:::i;:::-;4652:71;;4624:105;4556:183;;;;:::o;4746:241::-;;4850:2;4838:9;4829:7;4825:23;4821:32;4818:2;;;4866:1;4863;4856:12;4818:2;4901:1;4918:53;4963:7;4954:6;4943:9;4939:22;4918:53;:::i;:::-;4908:63;;4880:97;4812:175;;;;:::o;4994:291::-;;5123:2;5111:9;5102:7;5098:23;5094:32;5091:2;;;5139:1;5136;5129:12;5091:2;5174:1;5191:78;5261:7;5252:6;5241:9;5237:22;5191:78;:::i;:::-;5181:88;;5153:122;5085:200;;;;:::o;5292:646::-;;;;5464:3;5452:9;5443:7;5439:23;5435:33;5432:2;;;5481:1;5478;5471:12;5432:2;5516:1;5533:78;5603:7;5594:6;5583:9;5579:22;5533:78;:::i;:::-;5523:88;;5495:122;5648:2;5666:53;5711:7;5702:6;5691:9;5687:22;5666:53;:::i;:::-;5656:63;;5627:98;5784:2;5773:9;5769:18;5756:32;5808:18;5800:6;5797:30;5794:2;;;5840:1;5837;5830:12;5794:2;5860:62;5914:7;5905:6;5894:9;5890:22;5860:62;:::i;:::-;5850:72;;5735:193;5426:512;;;;;:::o;5945:1052::-;;;;;;6185:3;6173:9;6164:7;6160:23;6156:33;6153:2;;;6202:1;6199;6192:12;6153:2;6237:1;6254:78;6324:7;6315:6;6304:9;6300:22;6254:78;:::i;:::-;6244:88;;6216:122;6369:2;6387:53;6432:7;6423:6;6412:9;6408:22;6387:53;:::i;:::-;6377:63;;6348:98;6477:2;6495:78;6565:7;6556:6;6545:9;6541:22;6495:78;:::i;:::-;6485:88;;6456:123;6638:3;6627:9;6623:19;6610:33;6663:18;6655:6;6652:30;6649:2;;;6695:1;6692;6685:12;6649:2;6715:62;6769:7;6760:6;6749:9;6745:22;6715:62;:::i;:::-;6705:72;;6589:194;6842:3;6831:9;6827:19;6814:33;6867:18;6859:6;6856:30;6853:2;;;6899:1;6896;6889:12;6853:2;6919:62;6973:7;6964:6;6953:9;6949:22;6919:62;:::i;:::-;6909:72;;6793:194;6147:850;;;;;;;;:::o;7004:542::-;;;;7167:3;7155:9;7146:7;7142:23;7138:33;7135:2;;;7184:1;7181;7174:12;7135:2;7219:1;7236:78;7306:7;7297:6;7286:9;7282:22;7236:78;:::i;:::-;7226:88;;7198:122;7351:2;7369:53;7414:7;7405:6;7394:9;7390:22;7369:53;:::i;:::-;7359:63;;7330:98;7459:2;7477:53;7522:7;7513:6;7502:9;7498:22;7477:53;:::i;:::-;7467:63;;7438:98;7129:417;;;;;:::o;7553:241::-;;7657:2;7645:9;7636:7;7632:23;7628:32;7625:2;;;7673:1;7670;7663:12;7625:2;7708:1;7725:53;7770:7;7761:6;7750:9;7746:22;7725:53;:::i;:::-;7715:63;;7687:97;7619:175;;;;:::o;7801:366::-;;;7922:2;7910:9;7901:7;7897:23;7893:32;7890:2;;;7938:1;7935;7928:12;7890:2;7973:1;7990:53;8035:7;8026:6;8015:9;8011:22;7990:53;:::i;:::-;7980:63;;7952:97;8080:2;8098:53;8143:7;8134:6;8123:9;8119:22;8098:53;:::i;:::-;8088:63;;8059:98;7884:283;;;;;:::o;8175:365::-;;8358:142;8496:3;8488:6;8358:142;:::i;:::-;8529:4;8524:3;8520:14;8506:28;;8351:189;;;;:::o;8549:273::-;;8686:96;8778:3;8770:6;8686:96;:::i;:::-;8811:4;8806:3;8802:14;8788:28;;8679:143;;;;:::o;8830:142::-;8921:45;8960:5;8921:45;:::i;:::-;8916:3;8909:58;8903:69;;:::o;8979:137::-;9078:32;9104:5;9078:32;:::i;:::-;9073:3;9066:45;9060:56;;:::o;9123:113::-;9206:24;9224:5;9206:24;:::i;:::-;9201:3;9194:37;9188:48;;:::o;9306:1074::-;;9547:102;9643:5;9547:102;:::i;:::-;9662:134;9789:6;9784:3;9662:134;:::i;:::-;9655:141;;9817:104;9915:5;9817:104;:::i;:::-;9941:7;9969:1;9954:404;9979:6;9976:1;9973:13;9954:404;;;10046:6;10040:13;10067:159;10222:3;10207:13;10067:159;:::i;:::-;10060:166;;10243:108;10344:6;10243:108;:::i;:::-;10233:118;;10011:347;10001:1;9998;9994:9;9989:14;;9954:404;;;9958:14;10371:3;10364:10;;9526:854;;;;;;;:::o;10447:840::-;10620:77;10691:5;10620:77;:::i;:::-;10710:99;10802:6;10797:3;10710:99;:::i;:::-;10703:106;;10830:79;10903:5;10830:79;:::i;:::-;10929:7;10957:1;10942:333;10967:6;10964:1;10961:13;10942:333;;;11034:6;11028:13;11055:113;11164:3;11149:13;11055:113;:::i;:::-;11048:120;;11185:83;11261:6;11185:83;:::i;:::-;11175:93;;10999:276;10989:1;10986;10982:9;10977:14;;10942:333;;;10946:14;10599:688;;;;;:::o;11354:860::-;11537:77;11608:5;11537:77;:::i;:::-;11627:109;11729:6;11724:3;11627:109;:::i;:::-;11620:116;;11757:79;11830:5;11757:79;:::i;:::-;11856:7;11884:1;11869:333;11894:6;11891:1;11888:13;11869:333;;;11961:6;11955:13;11982:113;12091:3;12076:13;11982:113;:::i;:::-;11975:120;;12112:83;12188:6;12112:83;:::i;:::-;12102:93;;11926:276;11916:1;11913;11909:9;11904:14;;11869:333;;;11873:14;11516:698;;;;;:::o;12279:890::-;;12474:79;12547:5;12474:79;:::i;:::-;12566:111;12670:6;12665:3;12566:111;:::i;:::-;12559:118;;12698:81;12773:5;12698:81;:::i;:::-;12799:7;12827:1;12812:335;12837:6;12834:1;12831:13;12812:335;;;12904:6;12898:13;12925:113;13034:3;13019:13;12925:113;:::i;:::-;12918:120;;13055:85;13133:6;13055:85;:::i;:::-;13045:95;;12869:278;12859:1;12856;12852:9;12847:14;;12812:335;;;12816:14;13160:3;13153:10;;12453:716;;;;;;;:::o;13177:104::-;13254:21;13269:5;13254:21;:::i;:::-;13249:3;13242:34;13236:45;;:::o;13288:103::-;13361:24;13379:5;13361:24;:::i;:::-;13356:3;13349:37;13343:48;;:::o;13398:343::-;;13508:38;13540:5;13508:38;:::i;:::-;13558:70;13621:6;13616:3;13558:70;:::i;:::-;13551:77;;13633:52;13678:6;13673:3;13666:4;13659:5;13655:16;13633:52;:::i;:::-;13706:29;13728:6;13706:29;:::i;:::-;13701:3;13697:39;13690:46;;13488:253;;;;;:::o;13749:328::-;;13909:67;13973:2;13968:3;13909:67;:::i;:::-;13902:74;;14009:30;14005:1;14000:3;13996:11;13989:51;14068:2;14063:3;14059:12;14052:19;;13895:182;;;:::o;14086:385::-;;14246:67;14310:2;14305:3;14246:67;:::i;:::-;14239:74;;14346:34;14342:1;14337:3;14333:11;14326:55;14415:18;14410:2;14405:3;14401:12;14394:40;14462:2;14457:3;14453:12;14446:19;;14232:239;;;:::o;14480:327::-;;14640:67;14704:2;14699:3;14640:67;:::i;:::-;14633:74;;14740:29;14736:1;14731:3;14727:11;14720:50;14798:2;14793:3;14789:12;14782:19;;14626:181;;;:::o;14816:387::-;;14976:67;15040:2;15035:3;14976:67;:::i;:::-;14969:74;;15076:34;15072:1;15067:3;15063:11;15056:55;15145:20;15140:2;15135:3;15131:12;15124:42;15194:2;15189:3;15185:12;15178:19;;14962:241;;;:::o;15212:391::-;;15372:67;15436:2;15431:3;15372:67;:::i;:::-;15365:74;;15472:34;15468:1;15463:3;15459:11;15452:55;15541:24;15536:2;15531:3;15527:12;15520:46;15594:2;15589:3;15585:12;15578:19;;15358:245;;;:::o;15612:319::-;;15772:67;15836:2;15831:3;15772:67;:::i;:::-;15765:74;;15872:21;15868:1;15863:3;15859:11;15852:42;15922:2;15917:3;15913:12;15906:19;;15758:173;;;:::o;15940:389::-;;16100:67;16164:2;16159:3;16100:67;:::i;:::-;16093:74;;16200:34;16196:1;16191:3;16187:11;16180:55;16269:22;16264:2;16259:3;16255:12;16248:44;16320:2;16315:3;16311:12;16304:19;;16086:243;;;:::o;16338:377::-;;16498:67;16562:2;16557:3;16498:67;:::i;:::-;16491:74;;16598:34;16594:1;16589:3;16585:11;16578:55;16667:10;16662:2;16657:3;16653:12;16646:32;16706:2;16701:3;16697:12;16690:19;;16484:231;;;:::o;16724:324::-;;16884:67;16948:2;16943:3;16884:67;:::i;:::-;16877:74;;16984:26;16980:1;16975:3;16971:11;16964:47;17039:2;17034:3;17030:12;17023:19;;16870:178;;;:::o;17057:331::-;;17217:67;17281:2;17276:3;17217:67;:::i;:::-;17210:74;;17317:33;17313:1;17308:3;17304:11;17297:54;17379:2;17374:3;17370:12;17363:19;;17203:185;;;:::o;17397:383::-;;17557:67;17621:2;17616:3;17557:67;:::i;:::-;17550:74;;17657:34;17653:1;17648:3;17644:11;17637:55;17726:16;17721:2;17716:3;17712:12;17705:38;17771:2;17766:3;17762:12;17755:19;;17543:237;;;:::o;17789:372::-;;17949:67;18013:2;18008:3;17949:67;:::i;:::-;17942:74;;18049:34;18045:1;18040:3;18036:11;18029:55;18118:5;18113:2;18108:3;18104:12;18097:27;18152:2;18147:3;18143:12;18136:19;;17935:226;;;:::o;18170:328::-;;18330:67;18394:2;18389:3;18330:67;:::i;:::-;18323:74;;18430:30;18426:1;18421:3;18417:11;18410:51;18489:2;18484:3;18480:12;18473:19;;18316:182;;;:::o;18507:400::-;;18667:67;18731:2;18726:3;18667:67;:::i;:::-;18660:74;;18767:34;18763:1;18758:3;18754:11;18747:55;18836:33;18831:2;18826:3;18822:12;18815:55;18898:2;18893:3;18889:12;18882:19;;18653:254;;;:::o;18916:327::-;;19076:67;19140:2;19135:3;19076:67;:::i;:::-;19069:74;;19176:29;19172:1;19167:3;19163:11;19156:50;19234:2;19229:3;19225:12;19218:19;;19062:181;;;:::o;19252:319::-;;19412:67;19476:2;19471:3;19412:67;:::i;:::-;19405:74;;19512:21;19508:1;19503:3;19499:11;19492:42;19562:2;19557:3;19553:12;19546:19;;19398:173;;;:::o;19580:329::-;;19740:67;19804:2;19799:3;19740:67;:::i;:::-;19733:74;;19840:31;19836:1;19831:3;19827:11;19820:52;19900:2;19895:3;19891:12;19884:19;;19726:183;;;:::o;19918:319::-;;20078:67;20142:2;20137:3;20078:67;:::i;:::-;20071:74;;20178:21;20174:1;20169:3;20165:11;20158:42;20228:2;20223:3;20219:12;20212:19;;20064:173;;;:::o;20246:396::-;;20406:67;20470:2;20465:3;20406:67;:::i;:::-;20399:74;;20506:34;20502:1;20497:3;20493:11;20486:55;20575:29;20570:2;20565:3;20561:12;20554:51;20633:2;20628:3;20624:12;20617:19;;20392:250;;;:::o;20651:331::-;;20811:67;20875:2;20870:3;20811:67;:::i;:::-;20804:74;;20911:33;20907:1;20902:3;20898:11;20891:54;20973:2;20968:3;20964:12;20957:19;;20797:185;;;:::o;20991:319::-;;21151:67;21215:2;21210:3;21151:67;:::i;:::-;21144:74;;21251:21;21247:1;21242:3;21238:11;21231:42;21301:2;21296:3;21292:12;21285:19;;21137:173;;;:::o;21369:460::-;21502:4;21497:3;21493:14;21582:4;21575:5;21571:16;21565:23;21594:63;21651:4;21646:3;21642:14;21628:12;21594:63;:::i;:::-;21522:141;21733:4;21726:5;21722:16;21716:23;21745:63;21802:4;21797:3;21793:14;21779:12;21745:63;:::i;:::-;21673:141;21475:354;;;:::o;21887:470::-;22030:4;22025:3;22021:14;22110:4;22103:5;22099:16;22093:23;22122:63;22179:4;22174:3;22170:14;22156:12;22122:63;:::i;:::-;22050:141;22261:4;22254:5;22250:16;22244:23;22273:63;22330:4;22325:3;22321:14;22307:12;22273:63;:::i;:::-;22201:141;22003:354;;;:::o;22364:113::-;22447:24;22465:5;22447:24;:::i;:::-;22442:3;22435:37;22429:48;;:::o;22484:254::-;;22627:2;22616:9;22612:18;22604:26;;22641:87;22725:1;22714:9;22710:17;22701:6;22641:87;:::i;:::-;22598:140;;;;:::o;22745:460::-;;22936:2;22925:9;22921:18;22913:26;;22950:79;23026:1;23015:9;23011:17;23002:6;22950:79;:::i;:::-;23040:72;23108:2;23097:9;23093:18;23084:6;23040:72;:::i;:::-;23123;23191:2;23180:9;23176:18;23167:6;23123:72;:::i;:::-;22907:298;;;;;;:::o;23212:349::-;;23375:2;23364:9;23360:18;23352:26;;23389:79;23465:1;23454:9;23450:17;23441:6;23389:79;:::i;:::-;23479:72;23547:2;23536:9;23532:18;23523:6;23479:72;:::i;:::-;23346:215;;;;;:::o;23568:645::-;;23851:3;23840:9;23836:19;23828:27;;23866:71;23934:1;23923:9;23919:17;23910:6;23866:71;:::i;:::-;23948:122;24066:2;24055:9;24051:18;24042:6;23948:122;:::i;:::-;24081;24199:2;24188:9;24184:18;24175:6;24081:122;:::i;:::-;23822:391;;;;;;:::o;24220:562::-;;24493:2;24482:9;24478:18;24470:26;;24543:9;24537:4;24533:20;24529:1;24518:9;24514:17;24507:47;24568:204;24767:4;24758:6;24568:204;:::i;:::-;24560:212;;24464:318;;;;:::o;24789:719::-;;25136:3;25125:9;25121:19;25113:27;;25151:167;25315:1;25304:9;25300:17;25291:6;25151:167;:::i;:::-;25329:169;25493:3;25482:9;25478:19;25469:6;25329:169;:::i;:::-;25107:401;;;;;:::o;25515:470::-;;25742:2;25731:9;25727:18;25719:26;;25792:9;25786:4;25782:20;25778:1;25767:9;25763:17;25756:47;25817:158;25970:4;25961:6;25817:158;:::i;:::-;25809:166;;25713:272;;;;:::o;25992:2280::-;;26833:3;26822:9;26818:19;26810:27;;26884:9;26878:4;26874:20;26870:1;26859:9;26855:17;26848:47;26909:158;27062:4;27053:6;26909:158;:::i;:::-;26901:166;;27115:9;27109:4;27105:20;27100:2;27089:9;27085:18;27078:48;27140:158;27293:4;27284:6;27140:158;:::i;:::-;27132:166;;27346:9;27340:4;27336:20;27331:2;27320:9;27316:18;27309:48;27371:158;27524:4;27515:6;27371:158;:::i;:::-;27363:166;;27540:122;27658:2;27647:9;27643:18;27634:6;27540:122;:::i;:::-;27711:9;27705:4;27701:20;27695:3;27684:9;27680:19;27673:49;27736:158;27889:4;27880:6;27736:158;:::i;:::-;27728:166;;27905:73;27973:3;27962:9;27958:19;27949:6;27905:73;:::i;:::-;27989:123;28107:3;28096:9;28092:19;28083:6;27989:123;:::i;:::-;28161:9;28155:4;28151:20;28145:3;28134:9;28130:19;28123:49;28186:76;28257:4;28248:6;28186:76;:::i;:::-;28178:84;;26804:1468;;;;;;;;;;;:::o;28279:210::-;;28400:2;28389:9;28385:18;28377:26;;28414:65;28476:1;28465:9;28461:17;28452:6;28414:65;:::i;:::-;28371:118;;;;:::o;28496:306::-;;28641:2;28630:9;28626:18;28618:26;;28691:9;28685:4;28681:20;28677:1;28666:9;28662:17;28655:47;28716:76;28787:4;28778:6;28716:76;:::i;:::-;28708:84;;28612:190;;;;:::o;28809:416::-;;29009:2;28998:9;28994:18;28986:26;;29059:9;29053:4;29049:20;29045:1;29034:9;29030:17;29023:47;29084:131;29210:4;29084:131;:::i;:::-;29076:139;;28980:245;;;:::o;29232:416::-;;29432:2;29421:9;29417:18;29409:26;;29482:9;29476:4;29472:20;29468:1;29457:9;29453:17;29446:47;29507:131;29633:4;29507:131;:::i;:::-;29499:139;;29403:245;;;:::o;29655:416::-;;29855:2;29844:9;29840:18;29832:26;;29905:9;29899:4;29895:20;29891:1;29880:9;29876:17;29869:47;29930:131;30056:4;29930:131;:::i;:::-;29922:139;;29826:245;;;:::o;30078:416::-;;30278:2;30267:9;30263:18;30255:26;;30328:9;30322:4;30318:20;30314:1;30303:9;30299:17;30292:47;30353:131;30479:4;30353:131;:::i;:::-;30345:139;;30249:245;;;:::o;30501:416::-;;30701:2;30690:9;30686:18;30678:26;;30751:9;30745:4;30741:20;30737:1;30726:9;30722:17;30715:47;30776:131;30902:4;30776:131;:::i;:::-;30768:139;;30672:245;;;:::o;30924:416::-;;31124:2;31113:9;31109:18;31101:26;;31174:9;31168:4;31164:20;31160:1;31149:9;31145:17;31138:47;31199:131;31325:4;31199:131;:::i;:::-;31191:139;;31095:245;;;:::o;31347:416::-;;31547:2;31536:9;31532:18;31524:26;;31597:9;31591:4;31587:20;31583:1;31572:9;31568:17;31561:47;31622:131;31748:4;31622:131;:::i;:::-;31614:139;;31518:245;;;:::o;31770:416::-;;31970:2;31959:9;31955:18;31947:26;;32020:9;32014:4;32010:20;32006:1;31995:9;31991:17;31984:47;32045:131;32171:4;32045:131;:::i;:::-;32037:139;;31941:245;;;:::o;32193:416::-;;32393:2;32382:9;32378:18;32370:26;;32443:9;32437:4;32433:20;32429:1;32418:9;32414:17;32407:47;32468:131;32594:4;32468:131;:::i;:::-;32460:139;;32364:245;;;:::o;32616:416::-;;32816:2;32805:9;32801:18;32793:26;;32866:9;32860:4;32856:20;32852:1;32841:9;32837:17;32830:47;32891:131;33017:4;32891:131;:::i;:::-;32883:139;;32787:245;;;:::o;33039:416::-;;33239:2;33228:9;33224:18;33216:26;;33289:9;33283:4;33279:20;33275:1;33264:9;33260:17;33253:47;33314:131;33440:4;33314:131;:::i;:::-;33306:139;;33210:245;;;:::o;33462:416::-;;33662:2;33651:9;33647:18;33639:26;;33712:9;33706:4;33702:20;33698:1;33687:9;33683:17;33676:47;33737:131;33863:4;33737:131;:::i;:::-;33729:139;;33633:245;;;:::o;33885:416::-;;34085:2;34074:9;34070:18;34062:26;;34135:9;34129:4;34125:20;34121:1;34110:9;34106:17;34099:47;34160:131;34286:4;34160:131;:::i;:::-;34152:139;;34056:245;;;:::o;34308:416::-;;34508:2;34497:9;34493:18;34485:26;;34558:9;34552:4;34548:20;34544:1;34533:9;34529:17;34522:47;34583:131;34709:4;34583:131;:::i;:::-;34575:139;;34479:245;;;:::o;34731:416::-;;34931:2;34920:9;34916:18;34908:26;;34981:9;34975:4;34971:20;34967:1;34956:9;34952:17;34945:47;35006:131;35132:4;35006:131;:::i;:::-;34998:139;;34902:245;;;:::o;35154:416::-;;35354:2;35343:9;35339:18;35331:26;;35404:9;35398:4;35394:20;35390:1;35379:9;35375:17;35368:47;35429:131;35555:4;35429:131;:::i;:::-;35421:139;;35325:245;;;:::o;35577:416::-;;35777:2;35766:9;35762:18;35754:26;;35827:9;35821:4;35817:20;35813:1;35802:9;35798:17;35791:47;35852:131;35978:4;35852:131;:::i;:::-;35844:139;;35748:245;;;:::o;36000:416::-;;36200:2;36189:9;36185:18;36177:26;;36250:9;36244:4;36240:20;36236:1;36225:9;36221:17;36214:47;36275:131;36401:4;36275:131;:::i;:::-;36267:139;;36171:245;;;:::o;36423:416::-;;36623:2;36612:9;36608:18;36600:26;;36673:9;36667:4;36663:20;36659:1;36648:9;36644:17;36637:47;36698:131;36824:4;36698:131;:::i;:::-;36690:139;;36594:245;;;:::o;36846:416::-;;37046:2;37035:9;37031:18;37023:26;;37096:9;37090:4;37086:20;37082:1;37071:9;37067:17;37060:47;37121:131;37247:4;37121:131;:::i;:::-;37113:139;;37017:245;;;:::o;37269:416::-;;37469:2;37458:9;37454:18;37446:26;;37519:9;37513:4;37509:20;37505:1;37494:9;37490:17;37483:47;37544:131;37670:4;37544:131;:::i;:::-;37536:139;;37440:245;;;:::o;37692:322::-;;37869:2;37858:9;37854:18;37846:26;;37883:121;38001:1;37990:9;37986:17;37977:6;37883:121;:::i;:::-;37840:174;;;;:::o;38021:1394::-;;38542:3;38531:9;38527:19;38519:27;;38557:121;38675:1;38664:9;38660:17;38651:6;38557:121;:::i;:::-;38689:122;38807:2;38796:9;38792:18;38783:6;38689:122;:::i;:::-;38822:123;38940:3;38929:9;38925:19;38916:6;38822:123;:::i;:::-;38956:73;39024:3;39013:9;39009:19;39000:6;38956:73;:::i;:::-;39040:123;39158:3;39147:9;39143:19;39134:6;39040:123;:::i;:::-;39174:81;39250:3;39239:9;39235:19;39226:6;39174:81;:::i;:::-;39304:9;39298:4;39294:20;39288:3;39277:9;39273:19;39266:49;39329:76;39400:4;39391:6;39329:76;:::i;:::-;39321:84;;38513:902;;;;;;;;;;:::o;39422:222::-;;39549:2;39538:9;39534:18;39526:26;;39563:71;39631:1;39620:9;39616:17;39607:6;39563:71;:::i;:::-;39520:124;;;;:::o;39651:256::-;;39713:2;39707:9;39697:19;;39751:4;39743:6;39739:17;39850:6;39838:10;39835:22;39814:18;39802:10;39799:34;39796:62;39793:2;;;39871:1;39868;39861:12;39793:2;39891:10;39887:2;39880:22;39691:216;;;;:::o;39914:329::-;;40098:18;40090:6;40087:30;40084:2;;;40130:1;40127;40120:12;40084:2;40165:4;40157:6;40153:17;40145:25;;40228:4;40222;40218:15;40210:23;;40021:222;;;:::o;40250:321::-;;40393:18;40385:6;40382:30;40379:2;;;40425:1;40422;40415:12;40379:2;40492:4;40488:9;40481:4;40473:6;40469:17;40465:33;40457:41;;40556:4;40550;40546:15;40538:23;;40316:255;;;:::o;40578:199::-;;40712:3;40704:11;;40750:4;40745:3;40741:14;40733:22;;40698:79;;;:::o;40784:122::-;;40893:3;40885:11;;40879:27;;;:::o;40913:176::-;;41024:3;41016:11;;41062:4;41057:3;41053:14;41045:22;;41010:79;;;:::o;41096:185::-;;41253:5;41247:12;41237:22;;41218:63;;;:::o;41288:133::-;;41407:4;41397:14;;41385:36;;;:::o;41428:162::-;;41562:5;41556:12;41546:22;;41527:63;;;:::o;41597:121::-;;41690:5;41684:12;41674:22;;41655:63;;;:::o;41725:156::-;;41871:4;41866:3;41862:14;41854:22;;41848:33;;;:::o;41888:131::-;;42009:4;42004:3;42000:14;41992:22;;41986:33;;;:::o;42026:133::-;;42149:4;42144:3;42140:14;42132:22;;42126:33;;;:::o;42167:226::-;;42345:6;42340:3;42333:19;42382:4;42377:3;42373:14;42358:29;;42326:67;;;;:::o;42402:155::-;;42548:3;42533:18;;42526:31;;;;:::o;42566:165::-;;42722:3;42707:18;;42700:31;;;;:::o;42740:203::-;;42895:6;42890:3;42883:19;42932:4;42927:3;42923:14;42908:29;;42876:67;;;;:::o;42952:162::-;;43066:6;43061:3;43054:19;43103:4;43098:3;43094:14;43079:29;;43047:67;;;;:::o;43123:163::-;;43238:6;43233:3;43226:19;43275:4;43270:3;43266:14;43251:29;;43219:67;;;;:::o;43294:91::-;;43356:24;43374:5;43356:24;:::i;:::-;43345:35;;43339:46;;;:::o;43392:99::-;;43462:24;43480:5;43462:24;:::i;:::-;43451:35;;43445:46;;;:::o;43498:85::-;;43571:5;43564:13;43557:21;43546:32;;43540:43;;;:::o;43590:72::-;;43652:5;43641:16;;43635:27;;;:::o;43669:121::-;;43742:42;43735:5;43731:54;43720:65;;43714:76;;;:::o;43797:72::-;;43859:5;43848:16;;43842:27;;;:::o;43876:129::-;;43963:37;43994:5;43963:37;:::i;:::-;43950:50;;43944:61;;;:::o;44012:121::-;;44091:37;44122:5;44091:37;:::i;:::-;44078:50;;44072:61;;;:::o;44140:108::-;;44219:24;44237:5;44219:24;:::i;:::-;44206:37;;44200:48;;;:::o;44256:145::-;44337:6;44332:3;44327;44314:30;44393:1;44384:6;44379:3;44375:16;44368:27;44307:94;;;:::o;44410:268::-;44475:1;44482:101;44496:6;44493:1;44490:13;44482:101;;;44572:1;44567:3;44563:11;44557:18;44553:1;44548:3;44544:11;44537:39;44518:2;44515:1;44511:10;44506:15;;44482:101;;;44598:6;44595:1;44592:13;44589:2;;;44663:1;44654:6;44649:3;44645:16;44638:27;44589:2;44459:219;;;;:::o;44686:97::-;;44774:2;44770:7;44765:2;44758:5;44754:14;44750:28;44740:38;;44734:49;;;:::o;44791:133::-;44868:32;44894:5;44868:32;:::i;:::-;44861:5;44858:43;44848:2;;44915:1;44912;44905:12;44848:2;44842:82;:::o;44931:111::-;44997:21;45012:5;44997:21;:::i;:::-;44990:5;44987:32;44977:2;;45033:1;45030;45023:12;44977:2;44971:71;:::o;45049:117::-;45118:24;45136:5;45118:24;:::i;:::-;45111:5;45108:35;45098:2;;45157:1;45154;45147:12;45098:2;45092:74;:::o;45173:117::-;45242:24;45260:5;45242:24;:::i;:::-;45235:5;45232:35;45222:2;;45281:1;45278;45271:12;45222:2;45216:74;:::o

Swarm Source

ipfs://321c1bcb54c741f2a54dca27ed414b60293c46ce2739846ee509024cae256e3a
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.