Contract 0xe557c77Ed24df7cDF21ED55a8C56Ea36CeBD5BD2 2

 

Contract Overview

Balance:
0 BNB

BNB Value:
$0.00

Token:
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xf5ddfb1095d83cbd75761b6a9811e243b8edddc7ca4d868d4c823563511762640x9b0d85d3120817882021-10-25 15:27:382 days 25 mins ago0xc1e34c6889056339295045b01f4b0df372d2642f IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00068478
0x503538b91a0c3e71ab9c75c65e5d8af0f1b074c029f0365c035ba767b2943f3c0xc3b6dcdc117502272021-10-14 0:05:2313 days 15 hrs ago0x6cbac3b33ab0765df7f0910f39084baad4639861 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.0122059
0xcec7473a9a33be091a418a81d7496bea92810e7d1a2fa125791ec6ae54b5d58c0xc3b6dcdc116710942021-10-11 4:52:0416 days 11 hrs ago0x0d64b6f8d1cabdf81fd1a00321ac3f1cce267f4f IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.012311385
0x252ff380f6afa3097bed8a6a71f1cd9c3360be476ca92da96b94fe7c06ce2f5d0x042ed32a116192162021-10-09 9:30:2118 days 6 hrs ago0x0394f11bc6733589f25d8708e4573e96832c8625 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00114502
0x157b7d0d7a11f1cfa0381f41b2063902a8f4f762fa7a08385c12116fe50a554e0x9b0d85d3116191952021-10-09 9:29:1818 days 6 hrs ago0x0394f11bc6733589f25d8708e4573e96832c8625 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00068472
0x4fe7f706c27538c4fa89d305f0f130e3a61d93d2cd7d56cabca88e4e189cb5c10xc3b6dcdc114960972021-10-05 2:43:2122 days 13 hrs ago0x8f5b5b3e89e872abf59c83fc1427b39143ad1707 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.002078125
0x1473ebe7ca375083f8dbdcf379bfd2cd2e283b61c116937658bc21e5eab71fbe0xeff4d178114960422021-10-05 2:40:3622 days 13 hrs ago0xca0c53db67c467bd9dcd6a8290bf9b4d979c6a4e IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20.02735 BNB0.02545079
0x8271b6f0452a12e4adff4e7a9c01739f307b22fc373ad5ce8bc84a8e24d395060x9b0d85d3114955782021-10-05 2:17:2422 days 13 hrs ago0x8f5b5b3e89e872abf59c83fc1427b39143ad1707 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00068478
0xc697981d0b2a9ce8c7c2f5bf365f54bfc36f4b06d0bf8bdbe232dc2721af00de0xc3b6dcdc111729772021-09-23 19:19:2933 days 20 hrs ago0xe259ee56f5d07b346a9015da08b8de01e31798f5 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.01206189
0xefd8239c300796a4db7d755170edcd2dbba7f3d0a8ba81cd536befcf6ff3f0bf0x042ed32a111599442021-09-23 8:20:5434 days 7 hrs ago0xca0c53db67c467bd9dcd6a8290bf9b4d979c6a4e IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00114502
0x2bbe9c6fa8f11e12804833bf9e47f6071806d07986e98fdaba5859f447e79c080x9b0d85d3111599202021-09-23 8:19:4234 days 7 hrs ago0xca0c53db67c467bd9dcd6a8290bf9b4d979c6a4e IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00068478
0x6a878547f5ba3afb866d1bee3c6a0ea9659d14cea98f13676d569401aa8e1b480xc3b6dcdc110961542021-09-21 2:51:0236 days 13 hrs ago0x3f8e00ed64401af83bb712bece76ba60607269cc IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.011895115
0x74fd6f8221f1cec9ce7513985f14c55cc5ca583bd0a6c9ab89d96d67186482e20xc3b6dcdc108547832021-09-12 16:59:5544 days 22 hrs ago0xaf49836487fc699c68791fc80eb9e66db2b03ad4 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.011969795
0xb35bfe7e3792960b162b152b028b0438f5c0f832daa0fa5c470c2629dea79a750xc3b6dcdc108547552021-09-12 16:58:3144 days 22 hrs ago0xaf49836487fc699c68791fc80eb9e66db2b03ad4 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00198449
0x06c4babfa3d0ec626b33976b2f54df32e657e5870c2d7d0a4efd14f2226f31e70xc3b6dcdc106833942021-09-06 16:30:5450 days 23 hrs ago0x17378831c998bab44625e95874e22d4e947b762e IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.01204875
0xbc3dafa0d24dbe36798bcbff024dc4e24de7338c1e300dafa617609ecf5a7f9e0xc3b6dcdc105160982021-08-31 19:54:4556 days 19 hrs ago0xa858726a4ffde982ab38b08172e99c00cbdaa7aa IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.01197357
0x362493745d62ef046ba97fbc55771a624a5d55cf3164aae3168f2795c24a54810x9b0d85d3105044872021-08-31 10:03:5357 days 5 hrs ago0x132c99b67da06c8397c0964ab5645f442f6f90c6 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00068472
0x5e4a2dd7ae43dd27cd515fadec03722d0724c417e9eed330f191ee7a927dc78e0xc3b6dcdc103084732021-08-24 12:41:2564 days 3 hrs ago0xdb5126c9976889ac5166927e3fd1ac8e40a91334 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.011925215
0xbab8b5739e7db81bba73fc1a47c8898c352444d0f46feebc540350cf03d4f2ab0xeff4d178103084372021-08-24 12:39:1864 days 3 hrs ago0xc51741d9c3b171c6f1ba34e6611f368dd48b8539 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20.02735 BNB0.02527012
0x0a5ecb73570ca598485dcf927effe29edeca85a87a0d51923d5fab934451850a0x042ed32a102836132021-08-23 15:49:0265 days 4 mins ago0xc51741d9c3b171c6f1ba34e6611f368dd48b8539 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00060887
0xda91f6be968f90a042a47e9d1e0cee0b6359c917050b9a43d83e59182dcc8bf20xc3b6dcdc102801482021-08-23 12:50:5965 days 3 hrs ago0x2c5e9797c27f62f321d7a82a7d8cdd22127872ed IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.011895215
0x242dc1cd0e29cee34d78e1f0642e3d0ec2298e90777d371d29d09e7f532014fc0xc3b6dcdc102801172021-08-23 12:49:2665 days 3 hrs ago0x2c5e9797c27f62f321d7a82a7d8cdd22127872ed IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.0017621979
0x5915a70e1b7e121b66cfe0eaaee86d847e44a1ff69330cc1ecdcf5c776e2bfa60xc3b6dcdc102730142021-08-23 6:52:0565 days 9 hrs ago0x769ed3c3a1ed1a7148a169ba6065ff48b82e6db4 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.011895155
0x360641abafe3a818a949e7b22838a602191f73e6a7a6fdf5c8f9e044d12c5e670xc3b6dcdc102195292021-08-21 10:03:5667 days 5 hrs ago0xb3de746d56c652ea0390233a135a4011cacd9be5 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.01206205
0x7b8083ffd0a11d8b5af6e8fa210235c7773cbea3f18dd395733a1edde6df770b0x042ed32a101190192021-08-17 21:49:0670 days 18 hrs ago0x22161250b01f19cd774e22d1d39ba436f9a4d3e2 IN  0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20 BNB0.00060887
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x1473ebe7ca375083f8dbdcf379bfd2cd2e283b61c116937658bc21e5eab71fbe114960422021-10-05 2:40:3622 days 13 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xca0c53db67c467bd9dcd6a8290bf9b4d979c6a4e0.022348985 BNB
0x1473ebe7ca375083f8dbdcf379bfd2cd2e283b61c116937658bc21e5eab71fbe114960422021-10-05 2:40:3622 days 13 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.005001015 BNB
0xbab8b5739e7db81bba73fc1a47c8898c352444d0f46feebc540350cf03d4f2ab103084372021-08-24 12:39:1864 days 3 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xc51741d9c3b171c6f1ba34e6611f368dd48b85390.022389375 BNB
0xbab8b5739e7db81bba73fc1a47c8898c352444d0f46feebc540350cf03d4f2ab103084372021-08-24 12:39:1864 days 3 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.004960625 BNB
0x7f6fea998b9d82e46b85e09a8fafe534c135c0b0db5536d9eac8c42b7721db3099431252021-08-11 17:12:2576 days 22 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xc51741d9c3b171c6f1ba34e6611f368dd48b85390.022398505 BNB
0x7f6fea998b9d82e46b85e09a8fafe534c135c0b0db5536d9eac8c42b7721db3099431252021-08-11 17:12:2576 days 22 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.004951495 BNB
0xfe858ba00bca6332c403176d0f474d3e1cbe6d4cb9df0701fa8ecd0813ac146199125582021-08-10 15:31:1078 days 22 mins ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20x0581e9c45544c1024214c6c0abe8e3437474b5b00.022398505 BNB
0xfe858ba00bca6332c403176d0f474d3e1cbe6d4cb9df0701fa8ecd0813ac146199125582021-08-10 15:31:1078 days 22 mins ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.004951495 BNB
0x3632a819bd726084a8516fa8c4d99acc3077fa2462b052b5af752184a9723ee590463282021-07-10 22:40:09108 days 17 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xc51741d9c3b171c6f1ba34e6611f368dd48b85390.02240515 BNB
0x3632a819bd726084a8516fa8c4d99acc3077fa2462b052b5af752184a9723ee590463282021-07-10 22:40:09108 days 17 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00494485 BNB
0xb7b9ead0f33461ea43997aeadea4a99f81021c7eede8350550c035bd961c985f86527752021-06-27 4:46:08122 days 11 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xc51741d9c3b171c6f1ba34e6611f368dd48b85390.02242088 BNB
0xb7b9ead0f33461ea43997aeadea4a99f81021c7eede8350550c035bd961c985f86527752021-06-27 4:46:08122 days 11 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00492912 BNB
0xa48a5a98cd62835c34b3f0c53b1cf1c94938bf5f7e9c46a1e69246e810970c7481146072021-06-08 9:36:23141 days 6 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd2Shield Protocol: Deployer0.02238278 BNB
0xa48a5a98cd62835c34b3f0c53b1cf1c94938bf5f7e9c46a1e69246e810970c7481146072021-06-08 9:36:23141 days 6 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00496722 BNB
0x0cbf15096abf0e59d2f55cbcdb6c042d17e6c57d1aa09153ab61a8974908d84a75177182021-05-18 13:57:11162 days 1 hr ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20x0e074f5c93ad2fccd902642f7fcf86b5e9a95d650.022458175 BNB
0x0cbf15096abf0e59d2f55cbcdb6c042d17e6c57d1aa09153ab61a8974908d84a75177182021-05-18 13:57:11162 days 1 hr ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.004891825 BNB
0x34ea4293ef037540ae5a77527e42fdaa43167dfc7a16881c05dc4a68aa1b15b174288792021-05-15 10:48:06165 days 5 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20x922f693d58a5bdf8d9e6f6d6cd6e39642cebad850.022405055 BNB
0x34ea4293ef037540ae5a77527e42fdaa43167dfc7a16881c05dc4a68aa1b15b174288792021-05-15 10:48:06165 days 5 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.004944945 BNB
0xd4a108b4e947b85d9f523f45fec7d4a6ddd402b58995e129336cc4cdd2bb340974277972021-05-15 9:53:45165 days 5 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xefa6701099e2e36ee3b3b907f104b3811bdae67a0.022335505 BNB
0xd4a108b4e947b85d9f523f45fec7d4a6ddd402b58995e129336cc4cdd2bb340974277972021-05-15 9:53:45165 days 5 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.005014495 BNB
0x4cf62e361ecde59bbc1367475e8f48be0812a8db2eeea4fcfe9ed6bf3c83c3c674268672021-05-15 9:07:08165 days 6 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20x014743fb39c9040ceb2d985ae5de1966d33756bf0.02243664 BNB
0x4cf62e361ecde59bbc1367475e8f48be0812a8db2eeea4fcfe9ed6bf3c83c3c674268672021-05-15 9:07:08165 days 6 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00491336 BNB
0xdf007bedac28bd82446042e9c6d1801bb4bb1d220120fecf59e4ee75520d537a73797812021-05-13 17:02:43166 days 22 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20x4a40eb870dcf533d4dc097c3d87aafe9f64490a10.021408152 BNB
0xdf007bedac28bd82446042e9c6d1801bb4bb1d220120fecf59e4ee75520d537a73797812021-05-13 17:02:43166 days 22 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.005941848 BNB
0x6e4dcce7d6c96c232c8160619da533983d1badf0fbde46256088b5588a1e6ddd73740902021-05-13 12:11:56167 days 3 hrs ago 0xe557c77ed24df7cdf21ed55a8c56ea36cebd5bd20x922f693d58a5bdf8d9e6f6d6cd6e39642cebad850.022473935 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

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

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

000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d56000000000000000000000000076010bfc6377b24d10545e69840c9a6b79d6471000000000000000000000000d3a56c7fd5493268d299a4111a1b493c95b0b5690000000000000000000000000000000000000000000000000de0b6b3a7640000

-----Decoded View---------------
Arg [0] : _token (address): 0xe9e7cea3dedca5984780bafc599bd69add087d56
Arg [1] : _transfer (address): 0x076010bfc6377b24d10545e69840c9a6b79d6471
Arg [2] : _burn (address): 0xd3a56c7fd5493268d299a4111a1b493c95b0b569
Arg [3] : _unit (uint256): 1000000000000000000

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d56
Arg [1] : 000000000000000000000000076010bfc6377b24d10545e69840c9a6b79d6471
Arg [2] : 000000000000000000000000d3a56c7fd5493268d299a4111a1b493c95b0b569
Arg [3] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000


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.