Contract 0x9D529c70fD8e072786b721190f6E6B30e433690a

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x55ad5514bde54753ca13d43e2a7415800961183e470514bf29dd64b17082408d0x9b0d85d385789332021-06-24 15:05:25125 days 23 mins ago0x70860f1dd5108266f013d8deac7f1a831d8d909f IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0x1ebc0ff2ffc04752b73dc33e25e59cc5c77f9615bdf18767dbdc79a1d0b1f85b0x9b0d85d385529512021-06-23 17:22:51125 days 22 hrs ago0xdb213bae93809678bbbf906b96121b1f30925b25 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0x555b27d7b517213a3b0b77a01adfbf2b9fdd4200e815625dfffdb87be5741e950xc3b6dcdc84742292021-06-20 23:27:32128 days 16 hrs ago0x6a6a0a6ec8a80b2f47cad5b8654ddfcbb63dba49 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.01206091
0x0066264767adde27d10cf1719c8f4f38690c28715c711d24d6ce7b0a323ba7f60x042ed32a84741182021-06-20 23:21:59128 days 16 hrs ago0x6a6a0a6ec8a80b2f47cad5b8654ddfcbb63dba49 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00114425
0x0cf56bb982e8ebc8aabaa2d367f19453b2183c7cfa7f56c8525e2fbd4a1ec7510x9b0d85d384741052021-06-20 23:21:20128 days 16 hrs ago0x6a6a0a6ec8a80b2f47cad5b8654ddfcbb63dba49 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0xcd47201df495fae4d1a72f127d38f0d156be38f2bd747d2be920e929ce433a8e0x9b0d85d384320282021-06-19 12:09:32130 days 3 hrs ago0x687672ef80be21e5938abc4ad3b423687773af0a IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0x80ff73c66ef9a01702d823c82fa4d4ab88efa2add04111a3c7ecdb2a814231f10x9b0d85d378049312021-05-28 14:46:05152 days 42 mins ago0x1232d8b2ea16b64de34af079c22914cb1499201f IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0x74680e0aa5c72b2a72ee63de75d01c4611789915281e4860a0ae81d4730e75d20x9b0d85d377638442021-05-27 4:21:40153 days 11 hrs ago0x2cb49d9dfc66e4ad6b5b6d2e9ce3ac8c06fe9b18 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0x59f90d13d3320af01e00f896d5b9b519f893be65277e44c3ab9ffa85f49937c90x9b0d85d376942802021-05-24 18:00:25155 days 21 hrs ago0x688e80f25669c1d84eab8119fb3a41b76d161025 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0x521a46a385ca19f5f861bf4c6cddf61730d00f9fad5a18beee10aefde23f3b810xc3b6dcdc76492882021-05-23 4:19:39157 days 11 hrs ago0x032904f18ae8907990004a475dd3dd4f895b154d IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.011969535
0x19e4f11365b63c4fa3d643714b1eb52ee03c0f64c85750f653f53bcca393df090x9b0d85d375087222021-05-18 6:20:01162 days 9 hrs ago0x100e262d2235133bb9c035edc73ef0b632128d78 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0x54d85ae851b752ad256bc89aa9146574e82df53e25211401456b28f9983818ff0x9b0d85d374627172021-05-16 15:18:37164 days 10 mins ago0x60095164546cfee752630ab98dcc5f5d119282df IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0x97a362722909d8c2301b7528111e307e2a0dbec04890a1eb1d23c7ab7a4b25430x9b0d85d371877062021-05-06 14:08:20174 days 1 hr ago0xb3cd9f83cf4b6c21bf7c58f2b177b28d9565e9f0 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0x0b5b950aa3e0f5ae638645687cebf8ce6f5ae71b38f4e373c140881d9c7015610xc3b6dcdc71450032021-05-05 1:38:18175 days 13 hrs ago0xece0e3a96cea92a802932a3fa5b950ab6e5cbe3c IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.012214825
0x8d747aa6af884b62e1772f88b273c04978e7518520467ec42e0ea5143f022fe70x9b0d85d371173472021-05-04 2:24:03176 days 13 hrs ago0xb30e57382b5f67bf37b59d0e9a4bad1cd7053d5d IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0x9f7c9548d0d915d794eeedf63608354b76e4559534b5ed6ca41bbb8de3120c6f0x042ed32a71127972021-05-03 22:34:57176 days 16 hrs ago0xece0e3a96cea92a802932a3fa5b950ab6e5cbe3c IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.001247905
0x4a85536e8e37da1138e06fdc550eea5fcbf3aeca87dc77877dc4493c6c4c06d50x9b0d85d371071402021-05-03 17:49:44176 days 21 hrs ago0xece0e3a96cea92a802932a3fa5b950ab6e5cbe3c IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068466
0xf73b16e06b35d45f47a4263683eb0e566bc8dca1a5c2e19ecc89356f1cfe1bde0x042ed32a68252792021-04-23 20:52:48186 days 18 hrs ago0x032904f18ae8907990004a475dd3dd4f895b154d IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00114425
0xf846cbd0f6cc670458c7583a4166e9789e1e32158a7407465469ce2a5b2efdd40x9b0d85d368252412021-04-23 20:50:52186 days 18 hrs ago0x032904f18ae8907990004a475dd3dd4f895b154d IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0x74ad79292b9291f74c3189173879fec4e301208aab38d253a4fb5260bd0f72360x9b0d85d366836272021-04-18 21:02:48191 days 18 hrs ago0x8b047665d9b75cfa54274540c4ee70c9110a4dbf IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0x2fdb653497ea6662f26fe9350ac9e55774abfbafd090c6066c0dec4ab30148100x9b0d85d366350102021-04-17 4:29:20193 days 10 hrs ago0x01e72db85c91845a658808e93de73ce050750ed4 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0x31d697e409ffbf21374399cbcb21aeaa8f6f2a654f93765138e6d94548c397b10x9b0d85d366071252021-04-16 5:07:46194 days 10 hrs ago0xf2f09fa27678ff1e6133ef8c47c973eb41f326cf IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068472
0xa03bfa3af8163ace0a5421731eb6abe607ccbd5f93f00758f3857dc53be051180x9b0d85d365885522021-04-15 13:37:37195 days 1 hr ago0x0e73b141b7644c0680b0908c170b1fe274426138 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00068478
0xb1b6150e6c7d14ff139d3dc5a267905020b062ef416715ce46b19d357212fda00xc3b6dcdc63305012021-04-06 12:08:40204 days 3 hrs ago0x8ac4ed6897e186c2055806a76b6a26e5026d8aa7 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.00049308
0x78e035ab33f8adbcb5e20958426629e86c6876b6c2f8040eac5110b98a92b3d30xc3b6dcdc63304962021-04-06 12:08:25204 days 3 hrs ago0x8ac4ed6897e186c2055806a76b6a26e5026d8aa7 IN  0x9d529c70fd8e072786b721190f6e6b30e433690a0 BNB0.02475242
[ Download CSV Export 
Latest 4 internal transactions
Parent Txn Hash Block From To Value
0x98684f1cfab53c1d4617d27dafd1d10994056573a2099061dcc1541369eb9c4054483262021-03-06 16:47:45234 days 22 hrs ago 0x9d529c70fd8e072786b721190f6e6b30e433690a BakerySwap: BAKE Token0 BNB
0xb5e6e628cae669efd25ccdb6b53ef20baf11b4beada683a9d93e722eaeee7b0b53591492021-03-03 14:28:01238 days 1 hr ago 0x9d529c70fd8e072786b721190f6e6b30e433690a BakerySwap: BAKE Token0 BNB
0x67cedf6b4d91bd84f351cd6ab9f319b821df4f915ea13bd85afe9cf76244362d51232472021-02-23 7:47:48246 days 7 hrs ago 0x9d529c70fd8e072786b721190f6e6b30e433690a0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.04479701 BNB
0x67cedf6b4d91bd84f351cd6ab9f319b821df4f915ea13bd85afe9cf76244362d51232472021-02-23 7:47:48246 days 7 hrs ago 0x9d529c70fd8e072786b721190f6e6b30e433690a0xe6ee8e8829e65fe4ff406231ed1418dcb9afdb570.00990299 BNB
[ Download CSV Export 
Loading

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

Contract Name:
SuterERC20

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity Multiple files format)

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

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


contract SuterERC20 is SuterBase {

    ERC20 token;

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

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

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

        uint256 nativeAmount = toNativeAmount(unitAmount);

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

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

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

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



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

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

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

    InnerProductVerifier ip;

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

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

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

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

        InnerProductVerifier.InnerProductProof ipProof;
    }

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

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

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

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

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

        return proof;
    }
}

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

pragma solidity ^0.6.0;

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

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

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

pragma solidity ^0.6.0;

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

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

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

        return true;
    }

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

        _beforeTokenTransfer(sender, recipient, amount);

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

        emit Transfer(sender, recipient, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.6.0;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.6.0;

import "./IERC20.sol";

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

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

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

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

import "./Utils.sol";

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

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

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

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

        return verify(statement, proof, salt);
    }

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

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

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

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

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

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

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

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

        return true;
    }
}


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

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

contract SuterBase {

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

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

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

    //mapping(uint256 => bool) usedFeeStrategyNonces;


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

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

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

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

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

    mapping(bytes32 => bytes) guess;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        totalUsers = totalUsers + 1;
    }

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

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

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

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

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

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

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

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

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

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

        guess[yHash] = encGuess;
    }

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

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

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

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

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

        guess[yHash] = encGuess;

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

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

        uint256 startGas = gasleft();

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


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

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

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

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

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

        emit TransferOccurred(y);
    }
}



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

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

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

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

    InnerProductVerifier ip;

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

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

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

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

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

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

        InnerProductVerifier.InnerProductProof ipProof;
    }

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

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

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

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

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

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

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

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

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

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

        anonAuxiliaries.r = assemblePolynomials(anonAuxiliaries.f);

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

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

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

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

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

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

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

        return true;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return proof;
    }
}

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

library Utils {

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

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

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

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

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

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

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

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

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

    struct G1Point {
        bytes32 x;
        bytes32 y;
    }

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

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

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

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

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

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

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

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

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

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

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


Contract Security Audit

Contract ABI

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

608060405260018055606460025560016003556005600455601860075560006008556000600a556000600b556000600c556000600d556000600e556000600f5560006014553480156200005157600080fd5b506040516200446a3803806200446a8339818101604052810190620000779190620001bf565b828282336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060098190555050505083601660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050506200029d565b600081519050620001a28162000269565b92915050565b600081519050620001b98162000283565b92915050565b60008060008060808587031215620001d657600080fd5b6000620001e68782880162000191565b9450506020620001f98782880162000191565b93505060406200020c8782880162000191565b92505060606200021f87828801620001a8565b91505092959194509250565b600062000238826200023f565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000274816200022b565b81146200028057600080fd5b50565b6200028e816200025f565b81146200029a57600080fd5b50565b6141bd80620002ad6000396000f3fe6080604052600436106101d85760003560e01c806395e9524811610102578063bc939a4711610095578063de3d3d0811610064578063de3d3d08146106b3578063e708278f146106de578063eff4d17814610707578063f9a5375b14610723576101d8565b8063bc939a4714610609578063bff1f9e114610634578063c3b6dcdc1461065f578063d49d518114610688576101d8565b8063aae07890116100d1578063aae078901461054d578063ad7a672f14610576578063ae364d8f146105a1578063b1537596146105cc576101d8565b806395e952481461047e5780639b0d85d3146104a9578063a568ce51146104d2578063a9b05a5614610510576101d8565b806357d775f81161017a5780637d84839c116101495780637d84839c146103d25780637d882097146103fd578063840cd74c14610428578063907af6c014610453576101d8565b806357d775f8146103285780635a6fcd40146103535780637207f20e1461037e5780637601a39e146103a7576101d8565b806327d084e7116101b657806327d084e71461025a578063324db30f1461029757806354eea796146102c25780635524d548146102eb576101d8565b8063042ed32a146101dd5780630e2249321461020657806318131f6a14610231575b600080fd5b3480156101e957600080fd5b5061020460048036038101906101ff9190612eb5565b61074c565b005b34801561021257600080fd5b5061021b61085a565b6040516102289190613ecb565b60405180910390f35b34801561023d57600080fd5b506102586004803603810190610253919061303b565b610860565b005b34801561026657600080fd5b50610281600480360381019061027c9190612de6565b610900565b60405161028e9190613a4a565b60405180910390f35b3480156102a357600080fd5b506102ac610bad565b6040516102b99190613ecb565b60405180910390f35b3480156102ce57600080fd5b506102e960048036038101906102e49190613012565b610bb3565b005b3480156102f757600080fd5b50610312600480360381019061030d9190612e63565b610c4b565b60405161031f9190613b5a565b60405180910390f35b34801561033457600080fd5b5061033d610e59565b60405161034a9190613ecb565b60405180910390f35b34801561035f57600080fd5b50610368610e5f565b6040516103759190613ecb565b60405180910390f35b34801561038a57600080fd5b506103a560048036038101906103a0919061303b565b610e65565b005b3480156103b357600080fd5b506103bc610f05565b6040516103c99190613ecb565b60405180910390f35b3480156103de57600080fd5b506103e7610f0b565b6040516103f49190613ecb565b60405180910390f35b34801561040957600080fd5b50610412610f11565b60405161041f9190613ecb565b60405180910390f35b34801561043457600080fd5b5061043d610f17565b60405161044a9190613ecb565b60405180910390f35b34801561045f57600080fd5b50610468610f1d565b6040516104759190613ecb565b60405180910390f35b34801561048a57600080fd5b50610493610f23565b6040516104a09190613ecb565b60405180910390f35b3480156104b557600080fd5b506104d060048036038101906104cb9190612fc3565b610f29565b005b3480156104de57600080fd5b506104f960048036038101906104f49190612e8c565b6110fa565b604051610507929190613a6c565b60405180910390f35b34801561051c57600080fd5b5061053760048036038101906105329190612e8c565b611213565b6040516105449190613b75565b60405180910390f35b34801561055957600080fd5b50610574600480360381019061056f9190613012565b6112f4565b005b34801561058257600080fd5b5061058b61138c565b6040516105989190613ecb565b60405180910390f35b3480156105ad57600080fd5b506105b6611392565b6040516105c39190613ecb565b60405180910390f35b3480156105d857600080fd5b506105f360048036038101906105ee9190612e63565b611398565b6040516106009190613ecb565b60405180910390f35b34801561061557600080fd5b5061061e6113b0565b60405161062b9190613998565b60405180910390f35b34801561064057600080fd5b506106496113d4565b6040516106569190613ecb565b60405180910390f35b34801561066b57600080fd5b5061068660048036038101906106819190612f1c565b6113da565b005b34801561069457600080fd5b5061069d611624565b6040516106aa9190613ecb565b60405180910390f35b3480156106bf57600080fd5b506106c861162c565b6040516106d59190613ecb565b60405180910390f35b3480156106ea57600080fd5b5061070560048036038101906107009190613012565b611632565b005b610721600480360381019061071c9190612d27565b6116ca565b005b34801561072f57600080fd5b5061074a60048036038101906107459190612cfe565b611dd6565b005b610757838383611ea7565b600061076283612093565b9050601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b81526004016107c3939291906139b3565b602060405180830381600087803b1580156107dd57600080fd5b505af11580156107f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108159190612e3a565b610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084b90613d97565b60405180910390fd5b50505050565b600d5481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e590613dd7565b60405180910390fd5b81600181905550806002819055505050565b60606000835190508067ffffffffffffffff8111801561091f57600080fd5b5060405190808252806020026020018201604052801561095957816020015b610946612a07565b81526020019060019003908161093e5790505b50915060005b81811015610ba557600085828151811061097557fe5b602002602001015160405160200161098d9190613e37565b60405160208183030381529060405280519060200120905060106000828152602001908152602001600020600280602002604051908101604052809291906000905b82821015610a0b5783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906109cf565b50505050848381518110610a1b57fe5b60200260200101819052508460126000838152602001908152602001600020541015610b9757610a49612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b82821015610aaf578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610a73565b505050509050610afd81600060028110610ac557fe5b6020020151868581518110610ad657fe5b6020026020010151600060028110610aea57fe5b60200201516120f590919063ffffffff16565b858481518110610b0957fe5b6020026020010151600060028110610b1d57fe5b6020020181905250610b6d81600160028110610b3557fe5b6020020151868581518110610b4657fe5b6020026020010151600160028110610b5a57fe5b60200201516120f590919063ffffffff16565b858481518110610b7957fe5b6020026020010151600160028110610b8d57fe5b6020020181905250505b50808060010191505061095f565b505092915050565b600c5481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3890613c17565b60405180910390fd5b8060078190555050565b6000610c55612a34565b60405180604001604052806000801b81526020016000801b8152509050610c7a612a54565b604051806040016040528060106000878152602001908152602001600020600280602002604051908101604052809291906000905b82821015610ceb578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610caf565b50505050815260200160116000878152602001908152602001600020600280602002604051908101604052809291906000905b82821015610d5a578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610d1e565b505050508152509050610d988282600060028110610d7457fe5b6020020151600060028110610d8557fe5b602002015161213990919063ffffffff16565b8015610dd55750610dd48282600060028110610db057fe5b6020020151600160028110610dc157fe5b602002015161213990919063ffffffff16565b5b8015610e125750610e118282600160028110610ded57fe5b6020020151600060028110610dfe57fe5b602002015161213990919063ffffffff16565b5b8015610e4f5750610e4e8282600160028110610e2a57fe5b6020020151600160028110610e3b57fe5b602002015161213990919063ffffffff16565b5b1592505050919050565b60075481565b60145481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ef3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eea90613d37565b60405180910390fd5b81600381905550806004819055505050565b60045481565b60015481565b600e5481565b60025481565b60095481565b60035481565b610f31612a34565b610f77610f4f610f4085612161565b8661218d90919063ffffffff16565b610f6984610f5b6121c6565b61218d90919063ffffffff16565b6120f590919063ffffffff16565b90506000610fb1308684604051602001610f9393929190613a13565b6040516020818303038152906040528051906020012060001c61222e565b9050838114610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec90613cb7565b60405180910390fd5b6000856040516020016110089190613e37565b60405160208183030381529060405280519060200120905061102981610c4b565b15611069576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106090613bd7565b60405180910390fd5b856011600083815260200190815260200160002060006002811061108957fe5b6002020160008201518160000155602082015181600101559050506110ac6121c6565b601160008381526020019081526020016000206001600281106110cb57fe5b6002020160008201518160000155602082015181600101559050506001600b5401600b81905550505050505050565b611102612a07565b61110a612a07565b60008360405160200161111d9190613e37565b60405160208183030381529060405280519060200120905060106000828152602001908152602001600020600280602002604051908101604052809291906000905b8282101561119b57838260020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061115f565b50505050925060116000828152602001908152602001600020600280602002604051908101604052809291906000905b828210156112075783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906111cb565b50505050915050915091565b60606000826040516020016112289190613e37565b604051602081830303815290604052805190602001209050601560008281526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112e75780601f106112bc576101008083540402835291602001916112e7565b820191906000526020600020905b8154815290600101906020018083116112ca57829003601f168201915b5050505050915050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611382576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137990613cd7565b60405180910390fd5b8060098190555050565b600a5481565b600f5481565b60126020528060005260406000206000915090505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5481565b60006113e585612093565b905060006002546001548302816113f857fe5b0490506114088787878787612261565b600081111561152b57601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b815260040161148e9291906139ea565b602060405180830381600087803b1580156114a857600080fd5b505af11580156114bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e09190612e3a565b61151f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151690613d77565b60405180910390fd5b80600c5401600c819055505b601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338385036040518363ffffffff1660e01b815260040161158a9291906139ea565b602060405180830381600087803b1580156115a457600080fd5b505af11580156115b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115dc9190612e3a565b61161b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161290613c97565b60405180910390fd5b50505050505050565b63ffffffff81565b60085481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116b790613c57565b60405180910390fd5b8060088190555050565b60005a905060008451905060608167ffffffffffffffff811180156116ee57600080fd5b5060405190808252806020026020018201604052801561172857816020015b611715612a34565b81526020019060019003908161170d5790505b50905060608267ffffffffffffffff8111801561174457600080fd5b5060405190808252806020026020018201604052801561177e57816020015b61176b612a34565b8152602001906001900390816117635790505b509050828951146117c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117bb90613b97565b60405180910390fd5b60005b83811015611aa55760008882815181106117dd57fe5b60200260200101516040516020016117f59190613e37565b60405160208183030381529060405280519060200120905061181681610c4b565b611855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184c90613d57565b60405180910390fd5b61185e81612703565b611866612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b828210156118cc578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190611890565b5050505090506119098c84815181106118e157fe5b6020026020010151826000600281106118f657fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060006002811061192857fe5b6002020160008201518160000155602082015181600101559050506119678b8260016002811061195457fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060016002811061198657fe5b60020201600082015181600001556020820151816001015590505060106000838152602001908152602001600020600280602002604051908101604052809291906000905b82821015611a075783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906119cb565b505050509050611a448c8481518110611a1c57fe5b602002602001015182600060028110611a3157fe5b60200201516120f590919063ffffffff16565b858481518110611a5057fe5b6020026020010181905250611a7f8b82600160028110611a6c57fe5b60200201516120f590919063ffffffff16565b848481518110611a8b57fe5b6020026020010181905250505080806001019150506117c7565b50600086604051602001611ab99190613e37565b60405160208183030381529060405280519060200120905060005b601380549050811015611b48578160138281548110611aef57fe5b90600052602060002001541415611b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3290613c37565b60405180910390fd5b8080600101915050611ad4565b506013819080600181540180825580915050600190039060005260206000200160009091909190915055600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d2d5e70a84848d8d8d6014548e8e6040518963ffffffff1660e01b8152600401611bdd989796959493929190613ab8565b60206040518083038186803b158015611bf557600080fd5b505afa158015611c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2d9190612e3a565b611c6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6390613cf7565b60405180910390fd5b60005a8603905060003a600454600354840281611c8557fe5b040290506000811115611d485780341015611cd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ccc90613bf7565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d3b573d6000803e3d6000fd5b5080600d5401600d819055505b3373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051600060405180830381858888f19350505050158015611d90573d6000803e3d6000fd5b507f9b814ae8a45a4c40d4c60ffa92e0c4b76dec41407cb28b43df9daffa3685f9ac8a604051611dc09190613a96565b60405180910390a1505050505050505050505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5b90613bb7565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b63ffffffff8211158015611ec3575063ffffffff82600a540111155b611f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef990613c77565b60405180910390fd5b81600a6000828254019250508190555081600e600082825401925050819055506001600f60008282540192505081905550600083604051602001611f469190613e37565b604051602081830303815290604052805190602001209050611f6781610c4b565b611fa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f9d90613d57565b60405180910390fd5b611faf81612703565b611fb7612a34565b60116000838152602001908152602001600020600060028110611fd657fe5b600202016040518060400160405290816000820154815260200160018201548152505090506120276120188561200a6121c6565b61218d90919063ffffffff16565b826120f590919063ffffffff16565b9050806011600084815260200190815260200160002060006002811061204957fe5b6002020160008201518160000155602082015181600101559050508260156000848152602001908152602001600020908051906020019061208b929190612a81565b505050505050565b6000816000111580156120aa575063ffffffff8211155b6120e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e090613db7565b60405180910390fd5b60095482029050919050565b6120fd612a34565b6040518351815260208401516020820152825160408201526020830151606082015260408260808360065afa61213257600080fd5b5092915050565b600081600001518360000151148015612159575081602001518360200151145b905092915050565b6000817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001039050919050565b612195612a34565b604051835181526020840151602082015282604082015260408260608360075afa6121bf57600080fd5b5092915050565b6121ce612a34565b60405180604001604052807f077da99d806abd13c9f15ece5398525119d11e11e9836b2ee7d23f6159ad87d460001b81526020017f01485efa927f2ad41bff567eec88f32fb0a0f706588b4e41a8d587d008b7f87560001b815250905090565b60007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001828161225957fe5b069050919050565b83600a5410156122a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161229d90613d17565b60405180910390fd5b83600a600082825403925050819055506000856040516020016122c99190613e37565b6040516020818303038152906040528051906020012090506122ea81610c4b565b612329576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232090613d57565b60405180910390fd5b61233281612703565b61233a612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b828210156123a0578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612364565b5050505090506123eb6123cb6123b588612161565b6123bd6121c6565b61218d90919063ffffffff16565b826000600281106123d857fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060006002811061240a57fe5b60020201600082015181600001556020820151816001015590505060106000838152602001908152602001600020600280602002604051908101604052809291906000905b8282101561248b57838260020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061244f565b5050505090506124d66124b66124a088612161565b6124a86121c6565b61218d90919063ffffffff16565b826000600281106124c357fe5b60200201516120f590919063ffffffff16565b816000600281106124e357fe5b60200201819052506000856040516020016124fe9190613e37565b60405160208183030381529060405280519060200120905060005b60138054905081101561258d57816013828154811061253457fe5b90600052602060002001541415612580576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257790613c37565b60405180910390fd5b8080600101915050612519565b506013819080600181540180825580915050600190039060005260206000200160009091909190915055836015600085815260200190815260200160002090805190602001906125de929190612a81565b50600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391d16ac88360006002811061262a57fe5b60200201518460016002811061263c57fe5b60200201518b6014548b338c6040518863ffffffff1660e01b815260040161266a9796959493929190613e52565b60206040518083038186803b15801561268257600080fd5b505afa158015612696573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ba9190612e3a565b6126f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f090613df7565b60405180910390fd5b5050505050505050565b600080600854141561272257600754438161271a57fe5b04905061277c565b6001600854141561274057600754428161273857fe5b04905061277b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161277290613e17565b60405180910390fd5b5b80601260008481526020019081526020016000205410156129e35761279f612a54565b604051806040016040528060106000868152602001908152602001600020600280602002604051908101604052809291906000905b828210156128105783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906127d4565b50505050815260200160116000868152602001908152602001600020600280602002604051908101604052809291906000905b8282101561287f578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612843565b5050505081525090506128df8160016002811061289857fe5b60200201516000600281106128a957fe5b6020020151826000600281106128bb57fe5b60200201516000600281106128cc57fe5b60200201516120f590919063ffffffff16565b601060008581526020019081526020016000206000600281106128fe57fe5b6002020160008201518160000155602082015181600101559050506129708160016002811061292957fe5b602002015160016002811061293a57fe5b60200201518260006002811061294c57fe5b602002015160016002811061295d57fe5b60200201516120f590919063ffffffff16565b6010600085815260200190815260200160002060016002811061298f57fe5b6002020160008201518160000155602082015181600101559050506011600084815260200190815260200160002060006129c99190612b01565b816012600085815260200190815260200160002081905550505b806014541015612a03578060148190555060136000612a029190612b2c565b5b5050565b60405180604001604052806002905b612a1e612a34565b815260200190600190039081612a165790505090565b604051806040016040528060008019168152602001600080191681525090565b60405180604001604052806002905b612a6b612a07565b815260200190600190039081612a635790505090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612ac257805160ff1916838001178555612af0565b82800160010185558215612af0579182015b82811115612aef578251825591602001919060010190612ad4565b5b509050612afd9190612b4d565b5090565b5060008082016000905560018201600090555060020160008082016000905560018201600090555050565b5080546000825590600052602060002090810190612b4a9190612b6a565b50565b5b80821115612b66576000816000905550600101612b4e565b5090565b5b80821115612b83576000816000905550600101612b6b565b5090565b600081359050612b968161412b565b92915050565b600082601f830112612bad57600080fd5b8135612bc0612bbb82613f13565b613ee6565b91508181835260208401935060208101905083856040840282011115612be557600080fd5b60005b83811015612c155781612bfb8882612c9d565b845260208401935060408301925050600181019050612be8565b5050505092915050565b600081519050612c2e81614142565b92915050565b600081359050612c4381614159565b92915050565b600082601f830112612c5a57600080fd5b8135612c6d612c6882613f3b565b613ee6565b91508082526020830160208301858383011115612c8957600080fd5b612c948382846140d8565b50505092915050565b600060408284031215612caf57600080fd5b612cb96040613ee6565b90506000612cc984828501612c34565b6000830152506020612cdd84828501612c34565b60208301525092915050565b600081359050612cf881614170565b92915050565b600060208284031215612d1057600080fd5b6000612d1e84828501612b87565b91505092915050565b600080600080600060e08688031215612d3f57600080fd5b600086013567ffffffffffffffff811115612d5957600080fd5b612d6588828901612b9c565b9550506020612d7688828901612c9d565b945050606086013567ffffffffffffffff811115612d9357600080fd5b612d9f88828901612b9c565b9350506080612db088828901612c9d565b92505060c086013567ffffffffffffffff811115612dcd57600080fd5b612dd988828901612c49565b9150509295509295909350565b60008060408385031215612df957600080fd5b600083013567ffffffffffffffff811115612e1357600080fd5b612e1f85828601612b9c565b9250506020612e3085828601612ce9565b9150509250929050565b600060208284031215612e4c57600080fd5b6000612e5a84828501612c1f565b91505092915050565b600060208284031215612e7557600080fd5b6000612e8384828501612c34565b91505092915050565b600060408284031215612e9e57600080fd5b6000612eac84828501612c9d565b91505092915050565b600080600060808486031215612eca57600080fd5b6000612ed886828701612c9d565b9350506040612ee986828701612ce9565b925050606084013567ffffffffffffffff811115612f0657600080fd5b612f1286828701612c49565b9150509250925092565b600080600080600060e08688031215612f3457600080fd5b6000612f4288828901612c9d565b9550506040612f5388828901612ce9565b9450506060612f6488828901612c9d565b93505060a086013567ffffffffffffffff811115612f8157600080fd5b612f8d88828901612c49565b92505060c086013567ffffffffffffffff811115612faa57600080fd5b612fb688828901612c49565b9150509295509295909350565b600080600060808486031215612fd857600080fd5b6000612fe686828701612c9d565b9350506040612ff786828701612ce9565b925050606061300886828701612ce9565b9150509250925092565b60006020828403121561302457600080fd5b600061303284828501612ce9565b91505092915050565b6000806040838503121561304e57600080fd5b600061305c85828601612ce9565b925050602061306d85828601612ce9565b9150509250929050565b60006130838383613132565b60808301905092915050565b600061309b838361392b565b60408301905092915050565b6130b0816140a2565b82525050565b6130bf81614050565b82525050565b6130ce8161403e565b82525050565b60006130df82613f91565b6130e98185613fe4565b93506130f483613f67565b8060005b8381101561312557815161310c8882613077565b975061311783613fbd565b9250506001810190506130f8565b5085935050505092915050565b61313b81613f9c565b6131458184613ff5565b925061315082613f77565b8060005b83811015613181578151613168878261308f565b965061317383613fca565b925050600181019050613154565b505050505050565b61319281613f9c565b61319c8184614000565b92506131a782613f77565b8060005b838110156131d85781516131bf878261308f565b96506131ca83613fca565b9250506001810190506131ab565b505050505050565b60006131eb82613fa7565b6131f5818561400b565b935061320083613f81565b8060005b83811015613231578151613218888261308f565b975061322383613fd7565b925050600181019050613204565b5085935050505092915050565b61324781614062565b82525050565b6132568161406e565b82525050565b600061326782613fb2565b613271818561401c565b93506132818185602086016140e7565b61328a8161411a565b840191505092915050565b60006132a2601c8361402d565b91507f496e707574206172726179206c656e677468206d69736d6174636821000000006000830152602082019050919050565b60006132e260308361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765206167656e63792e000000000000000000000000000000006020830152604082019050919050565b6000613348601b8361402d565b91507f4163636f756e7420616c726561647920726567697374657265642100000000006000830152602082019050919050565b600061338860328361402d565b91507f4e6f7420656e6f756768206665652073656e742077697468207468652074726160008301527f6e73666572207472616e73616374696f6e2e00000000000000000000000000006020830152604082019050919050565b60006133ee60368361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e67652065706f6368206c656e6774682e000000000000000000006020830152604082019050919050565b600061345460138361402d565b91507f4e6f6e636520616c7265616479207365656e21000000000000000000000000006000830152602082019050919050565b600061349460348361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e67652065706f636820626173652e0000000000000000000000006020830152604082019050919050565b60006134fa60288361402d565b91507f46756e642070757368657320636f6e74726163742070617374206d6178696d7560008301527f6d2076616c75652e0000000000000000000000000000000000000000000000006020830152604082019050919050565b600061356060188361402d565b91507f4661696c20746f207472616e7366657220746f6b656e732e00000000000000006000830152602082019050919050565b60006135a0601f8361402d565b91507f496e76616c696420726567697374726174696f6e207369676e617475726521006000830152602082019050919050565b60006135e0602e8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e676520756e69742e0000000000000000000000000000000000006020830152604082019050919050565b600061364660238361402d565b91507f5472616e736665722070726f6f6620766572696669636174696f6e206661696c60008301527f65642100000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006136ac601c8361402d565b91507f4275726e206661696c73207468652073616e69747920636865636b2e000000006000830152602082019050919050565b60006136ec603f8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765207472616e73666572206665652073747261746567792e006020830152604082019050919050565b6000613752601b8361402d565b91507f4163636f756e74206e6f742079657420726567697374657265642e00000000006000830152602082019050919050565b600061379260138361402d565b91507f4661696c20746f20636861726765206665652e000000000000000000000000006000830152602082019050919050565b60006137d2601d8361402d565b91507f4e617469766520277472616e7366657246726f6d27206661696c65642e0000006000830152602082019050919050565b600061381260138361402d565b91507f416d6f756e74206f7574206f662072616e6765000000000000000000000000006000830152602082019050919050565b6000613852603b8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765206275726e206665652073747261746567792e00000000006020830152604082019050919050565b60006138b8601f8361402d565b91507f4275726e2070726f6f6620766572696669636174696f6e206661696c656421006000830152602082019050919050565b60006138f860138361402d565b91507f496e76616c69642065706f636820626173652e000000000000000000000000006000830152602082019050919050565b604082016000820151613941600085018261324d565b506020820151613954602085018261324d565b50505050565b604082016000820151613970600085018261324d565b506020820151613983602085018261324d565b50505050565b61399281614098565b82525050565b60006020820190506139ad60008301846130b6565b92915050565b60006060820190506139c860008301866130a7565b6139d560208301856130c5565b6139e26040830184613989565b949350505050565b60006040820190506139ff60008301856130a7565b613a0c6020830184613989565b9392505050565b600060a082019050613a2860008301866130c5565b613a35602083018561395a565b613a42606083018461395a565b949350505050565b60006020820190508181036000830152613a6481846130d4565b905092915050565b600061010082019050613a826000830185613189565b613a8f6080830184613189565b9392505050565b60006020820190508181036000830152613ab081846131e0565b905092915050565b6000610140820190508181036000830152613ad3818b6131e0565b90508181036020830152613ae7818a6131e0565b90508181036040830152613afb81896131e0565b9050613b0a606083018861395a565b81810360a0830152613b1c81876131e0565b9050613b2b60c0830186613989565b613b3860e083018561395a565b818103610120830152613b4b818461325c565b90509998505050505050505050565b6000602082019050613b6f600083018461323e565b92915050565b60006020820190508181036000830152613b8f818461325c565b905092915050565b60006020820190508181036000830152613bb081613295565b9050919050565b60006020820190508181036000830152613bd0816132d5565b9050919050565b60006020820190508181036000830152613bf08161333b565b9050919050565b60006020820190508181036000830152613c108161337b565b9050919050565b60006020820190508181036000830152613c30816133e1565b9050919050565b60006020820190508181036000830152613c5081613447565b9050919050565b60006020820190508181036000830152613c7081613487565b9050919050565b60006020820190508181036000830152613c90816134ed565b9050919050565b60006020820190508181036000830152613cb081613553565b9050919050565b60006020820190508181036000830152613cd081613593565b9050919050565b60006020820190508181036000830152613cf0816135d3565b9050919050565b60006020820190508181036000830152613d1081613639565b9050919050565b60006020820190508181036000830152613d308161369f565b9050919050565b60006020820190508181036000830152613d50816136df565b9050919050565b60006020820190508181036000830152613d7081613745565b9050919050565b60006020820190508181036000830152613d9081613785565b9050919050565b60006020820190508181036000830152613db0816137c5565b9050919050565b60006020820190508181036000830152613dd081613805565b9050919050565b60006020820190508181036000830152613df081613845565b9050919050565b60006020820190508181036000830152613e10816138ab565b9050919050565b60006020820190508181036000830152613e30816138eb565b9050919050565b6000604082019050613e4c600083018461395a565b92915050565b600061016082019050613e68600083018a61395a565b613e75604083018961395a565b613e82608083018861395a565b613e8f60c0830187613989565b613e9c60e083018661395a565b613eaa6101208301856130a7565b818103610140830152613ebd818461325c565b905098975050505050505050565b6000602082019050613ee06000830184613989565b92915050565b6000604051905081810181811067ffffffffffffffff82111715613f0957600080fd5b8060405250919050565b600067ffffffffffffffff821115613f2a57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115613f5257600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050919050565b6000819050602082019050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600061404982614078565b9050919050565b600061405b82614078565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006140ad826140b4565b9050919050565b60006140bf826140c6565b9050919050565b60006140d182614078565b9050919050565b82818337600083830152505050565b60005b838110156141055780820151818401526020810190506140ea565b83811115614114576000848401525b50505050565b6000601f19601f8301169050919050565b61413481614050565b811461413f57600080fd5b50565b61414b81614062565b811461415657600080fd5b50565b6141628161406e565b811461416d57600080fd5b50565b61417981614098565b811461418457600080fd5b5056fea2646970667358221220321c1bcb54c741f2a54dca27ed414b60293c46ce2739846ee509024cae256e3a64736f6c634300060c0033000000000000000000000000e9e7cea3dedca5984780bafc599bd69add087d56000000000000000000000000076010bfc6377b24d10545e69840c9a6b79d6471000000000000000000000000d3a56c7fd5493268d299a4111a1b493c95b0b5690000000000000000000000000000000000000000000000000de0b6b3a7640000

Deployed ByteCode Sourcemap

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

Swarm Source

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