Contract 0x617edfadeC530aE747088672831EaC5B1A6A5220 2

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x75d0d7e49afe749de7f8ab390307eb1d001a4bbbb3542e3d59743d4ac42724880x042ed32a116198842021-10-09 10:03:4512 days 8 hrs ago0x3f0500b79c099dfe2638d0faf1c03f56b90d12d1 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00072449
0x1ff225fb430fd72ce955ec079e6ce9b747a8ab9b1f92476779b4fbf4929f029f0x9b0d85d3115134772021-10-05 17:12:5216 days 1 hr ago0xc6d9c2b5478f2d3c51865685eb55486f0b2dc2b8 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068478
0xf68ba691984f9385874d42144c8157ee704aafbc292e7f0718913f2d4c38c9770x042ed32a111986772021-09-24 16:47:0727 days 1 hr ago0x09d345a6d9b6b174a4e709c8d87e7e4a106457ff IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00143176
0xa6d9226b25b6277a28fea284ae36f97bfd37aca31e96a0adb03078b93ca412530x042ed32a111986602021-09-24 16:46:1627 days 1 hr ago0x09d345a6d9b6b174a4e709c8d87e7e4a106457ff IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00143176
0xc4dbf7299e47d309af93a1acf4b1ac6e2f2709c056df0ceebb4cf870ee610bf50x9b0d85d3111885302021-09-24 8:18:1327 days 10 hrs ago0x09d345a6d9b6b174a4e709c8d87e7e4a106457ff IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068478
0xe0b767f40a904c27f0289d985911855abfa6d7c8b7614d0bbec5733ebceb60fd0x9b0d85d3111830692021-09-24 3:44:5227 days 14 hrs ago0x048a3ef0d65ac08591d5a7af5bdb9a240337cc48 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068466
0x8e13c9176a6b9c97a30d393803f53a8bad20968346f86109e240f7357adba3b80x9b0d85d3111538402021-09-23 3:14:0328 days 15 hrs ago0xbcf3c7662f5aa08b6cc2fde5ee9d027281588436 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068472
0xf37ed8f0f088e52d738a6c328c4a6c8efacac625ad6eb0cb43a0f44fca2324a70x9b0d85d3107903152021-09-10 10:48:4741 days 7 hrs ago0xf449c2e349a210afc9fabb32ac45e214a6cf28dc IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068478
0x0dadf832b61435bc660a200209f87f4208c900e824388de22463c4b8aa1cc1e70x9b0d85d3105982312021-09-03 17:19:3148 days 1 hr ago0x706dd0d5ded69836551e12be19dae4e5e30e4d08 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068472
0x12e4e38327521c11d271f7c57cd951927840390e973c8ecf59079426965a2ebc0x9b0d85d3105077072021-08-31 12:48:0651 days 5 hrs ago0x0313611f7f4af674695dacddc92352ad5e3d9053 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068478
0xa209bbfec5b3b4e558998993467fbad66061785c8229145bf825aa25301e37560x9b0d85d3105056612021-08-31 11:02:4251 days 7 hrs ago0xa0318c16908405a6ea01309cfc4481702ae4fdc9 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068478
0x761f7326286c1bb894e87b701afc85e12ee57035be796f35bb41be99d04aed120x9b0d85d3105040242021-08-31 9:40:4451 days 8 hrs ago0x75535d7ed58682dd1f2c1faccda0e81e8c7792db IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068478
0xd61297fc73a34c3654d8f2045bfa1c4a74e7189628f793079608eebb07d39a390x9b0d85d3105012842021-08-31 7:20:4651 days 11 hrs ago0xc81b1c5691ce7680ffa77118477ed4b30a13f4c1 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.0006984144
0x7277e48dd21ae91ef0b572fea5929d64ae425dcf1ff4c70fdbea81d2a1b347a20x042ed32a102976122021-08-24 3:33:0058 days 15 hrs ago0xb495692d3b94c7a54eeca4a887fbeacb0cfe5902 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00143182
0xd80624c713cf0ad0087b088b51fa05ad403e2e1703a4ea62aeaa87174c3f8b470x9b0d85d3102975782021-08-24 3:31:1858 days 15 hrs ago0xb495692d3b94c7a54eeca4a887fbeacb0cfe5902 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068478
0xa1801451408319d481f6ad4a211ba918721e5f0dc9b8d809fac1dd52acb92f030x042ed32a102068872021-08-20 23:28:0961 days 19 hrs ago0x78bd86640dd12fdbda74749d817da7a0dda02e68 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00143182
0x7c2f0efa98bd822fc37deb8520f3f3a86555b691b5e5c789b6534a7c26c3d34d0x042ed32a102067892021-08-20 23:23:1561 days 19 hrs ago0x78bd86640dd12fdbda74749d817da7a0dda02e68 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00143182
0x49ae541fcc768eb1a1a129af61239044e1e2b55e2f426e97f9e47d0252227c8f0xc3b6dcdc101719012021-08-19 18:08:2663 days 31 mins ago0x0064b4282b475f5c00ecf6a00f069ed81a50f8e0 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.01200878
0xdd6ef5246a2117c85c53c8100a9b8708aa26f528162ad85f744feafb3d1592740xc3b6dcdc101718882021-08-19 18:07:4763 days 31 mins ago0x0064b4282b475f5c00ecf6a00f069ed81a50f8e0 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.009821545
0xf3b195029e5eb7d196197d400394616f6443a52f7697bea3286f0edb3bc29fba0xc3b6dcdc101716212021-08-19 17:54:2663 days 45 mins ago0x0064b4282b475f5c00ecf6a00f069ed81a50f8e0 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.004935625
0x9f005f4932103d6061ae2c7aa43e3b6b0ef56ed1e18ee1396a5ec8315886d5ca0xc3b6dcdc101715972021-08-19 17:53:1463 days 46 mins ago0x0064b4282b475f5c00ecf6a00f069ed81a50f8e0 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.002474685
0xdea3e02b78030d88991ffc085a6862d218a39d251aed678cb0bb817735a58c6c0x9b0d85d3101464982021-08-18 20:44:4763 days 21 hrs ago0x3d446cda1caf5953e287e320bda175d26bb60d01 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00068472
0x2c3803a34a69ec5f84b9e7b485b94f2b93a87af8ae71cba07093ea4dc2e379180xc3b6dcdc101358912021-08-18 11:53:1864 days 6 hrs ago0x7ca24eac4cf3c0359631da0544db3618505319a4 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.011930625
0x6d0f9234ce22b46a257fafc809fb8731045d082f1a70b65fb7b5067a4849240c0xc3b6dcdc101358802021-08-18 11:52:4564 days 6 hrs ago0x7ca24eac4cf3c0359631da0544db3618505319a4 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.001748085
0x31fdeb3ba9ffe27060d2f775ac5195172c9aabdfcf8815de27434d50e696c8150x042ed32a100996152021-08-17 5:37:3465 days 13 hrs ago0xb495692d3b94c7a54eeca4a887fbeacb0cfe5902 IN  0x617edfadec530ae747088672831eac5b1a6a52200 BNB0.00143176
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

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

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"}]

608060405260018055606460025560016003556005600455601860075560006008556000600a556000600b556000600c556000600d556000600e556000600f5560006014553480156200005157600080fd5b506040516200446a3803806200446a8339818101604052810190620000779190620001bf565b828282336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060098190555050505083601660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050506200029d565b600081519050620001a28162000269565b92915050565b600081519050620001b98162000283565b92915050565b60008060008060808587031215620001d657600080fd5b6000620001e68782880162000191565b9450506020620001f98782880162000191565b93505060406200020c8782880162000191565b92505060606200021f87828801620001a8565b91505092959194509250565b600062000238826200023f565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000274816200022b565b81146200028057600080fd5b50565b6200028e816200025f565b81146200029a57600080fd5b50565b6141bd80620002ad6000396000f3fe6080604052600436106101d85760003560e01c806395e9524811610102578063bc939a4711610095578063de3d3d0811610064578063de3d3d08146106b3578063e708278f146106de578063eff4d17814610707578063f9a5375b14610723576101d8565b8063bc939a4714610609578063bff1f9e114610634578063c3b6dcdc1461065f578063d49d518114610688576101d8565b8063aae07890116100d1578063aae078901461054d578063ad7a672f14610576578063ae364d8f146105a1578063b1537596146105cc576101d8565b806395e952481461047e5780639b0d85d3146104a9578063a568ce51146104d2578063a9b05a5614610510576101d8565b806357d775f81161017a5780637d84839c116101495780637d84839c146103d25780637d882097146103fd578063840cd74c14610428578063907af6c014610453576101d8565b806357d775f8146103285780635a6fcd40146103535780637207f20e1461037e5780637601a39e146103a7576101d8565b806327d084e7116101b657806327d084e71461025a578063324db30f1461029757806354eea796146102c25780635524d548146102eb576101d8565b8063042ed32a146101dd5780630e2249321461020657806318131f6a14610231575b600080fd5b3480156101e957600080fd5b5061020460048036038101906101ff9190612eb5565b61074c565b005b34801561021257600080fd5b5061021b61085a565b6040516102289190613ecb565b60405180910390f35b34801561023d57600080fd5b506102586004803603810190610253919061303b565b610860565b005b34801561026657600080fd5b50610281600480360381019061027c9190612de6565b610900565b60405161028e9190613a4a565b60405180910390f35b3480156102a357600080fd5b506102ac610bad565b6040516102b99190613ecb565b60405180910390f35b3480156102ce57600080fd5b506102e960048036038101906102e49190613012565b610bb3565b005b3480156102f757600080fd5b50610312600480360381019061030d9190612e63565b610c4b565b60405161031f9190613b5a565b60405180910390f35b34801561033457600080fd5b5061033d610e59565b60405161034a9190613ecb565b60405180910390f35b34801561035f57600080fd5b50610368610e5f565b6040516103759190613ecb565b60405180910390f35b34801561038a57600080fd5b506103a560048036038101906103a0919061303b565b610e65565b005b3480156103b357600080fd5b506103bc610f05565b6040516103c99190613ecb565b60405180910390f35b3480156103de57600080fd5b506103e7610f0b565b6040516103f49190613ecb565b60405180910390f35b34801561040957600080fd5b50610412610f11565b60405161041f9190613ecb565b60405180910390f35b34801561043457600080fd5b5061043d610f17565b60405161044a9190613ecb565b60405180910390f35b34801561045f57600080fd5b50610468610f1d565b6040516104759190613ecb565b60405180910390f35b34801561048a57600080fd5b50610493610f23565b6040516104a09190613ecb565b60405180910390f35b3480156104b557600080fd5b506104d060048036038101906104cb9190612fc3565b610f29565b005b3480156104de57600080fd5b506104f960048036038101906104f49190612e8c565b6110fa565b604051610507929190613a6c565b60405180910390f35b34801561051c57600080fd5b5061053760048036038101906105329190612e8c565b611213565b6040516105449190613b75565b60405180910390f35b34801561055957600080fd5b50610574600480360381019061056f9190613012565b6112f4565b005b34801561058257600080fd5b5061058b61138c565b6040516105989190613ecb565b60405180910390f35b3480156105ad57600080fd5b506105b6611392565b6040516105c39190613ecb565b60405180910390f35b3480156105d857600080fd5b506105f360048036038101906105ee9190612e63565b611398565b6040516106009190613ecb565b60405180910390f35b34801561061557600080fd5b5061061e6113b0565b60405161062b9190613998565b60405180910390f35b34801561064057600080fd5b506106496113d4565b6040516106569190613ecb565b60405180910390f35b34801561066b57600080fd5b5061068660048036038101906106819190612f1c565b6113da565b005b34801561069457600080fd5b5061069d611624565b6040516106aa9190613ecb565b60405180910390f35b3480156106bf57600080fd5b506106c861162c565b6040516106d59190613ecb565b60405180910390f35b3480156106ea57600080fd5b5061070560048036038101906107009190613012565b611632565b005b610721600480360381019061071c9190612d27565b6116ca565b005b34801561072f57600080fd5b5061074a60048036038101906107459190612cfe565b611dd6565b005b610757838383611ea7565b600061076283612093565b9050601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b81526004016107c3939291906139b3565b602060405180830381600087803b1580156107dd57600080fd5b505af11580156107f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108159190612e3a565b610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084b90613d97565b60405180910390fd5b50505050565b600d5481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e590613dd7565b60405180910390fd5b81600181905550806002819055505050565b60606000835190508067ffffffffffffffff8111801561091f57600080fd5b5060405190808252806020026020018201604052801561095957816020015b610946612a07565b81526020019060019003908161093e5790505b50915060005b81811015610ba557600085828151811061097557fe5b602002602001015160405160200161098d9190613e37565b60405160208183030381529060405280519060200120905060106000828152602001908152602001600020600280602002604051908101604052809291906000905b82821015610a0b5783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906109cf565b50505050848381518110610a1b57fe5b60200260200101819052508460126000838152602001908152602001600020541015610b9757610a49612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b82821015610aaf578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610a73565b505050509050610afd81600060028110610ac557fe5b6020020151868581518110610ad657fe5b6020026020010151600060028110610aea57fe5b60200201516120f590919063ffffffff16565b858481518110610b0957fe5b6020026020010151600060028110610b1d57fe5b6020020181905250610b6d81600160028110610b3557fe5b6020020151868581518110610b4657fe5b6020026020010151600160028110610b5a57fe5b60200201516120f590919063ffffffff16565b858481518110610b7957fe5b6020026020010151600160028110610b8d57fe5b6020020181905250505b50808060010191505061095f565b505092915050565b600c5481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3890613c17565b60405180910390fd5b8060078190555050565b6000610c55612a34565b60405180604001604052806000801b81526020016000801b8152509050610c7a612a54565b604051806040016040528060106000878152602001908152602001600020600280602002604051908101604052809291906000905b82821015610ceb578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610caf565b50505050815260200160116000878152602001908152602001600020600280602002604051908101604052809291906000905b82821015610d5a578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610d1e565b505050508152509050610d988282600060028110610d7457fe5b6020020151600060028110610d8557fe5b602002015161213990919063ffffffff16565b8015610dd55750610dd48282600060028110610db057fe5b6020020151600160028110610dc157fe5b602002015161213990919063ffffffff16565b5b8015610e125750610e118282600160028110610ded57fe5b6020020151600060028110610dfe57fe5b602002015161213990919063ffffffff16565b5b8015610e4f5750610e4e8282600160028110610e2a57fe5b6020020151600160028110610e3b57fe5b602002015161213990919063ffffffff16565b5b1592505050919050565b60075481565b60145481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ef3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eea90613d37565b60405180910390fd5b81600381905550806004819055505050565b60045481565b60015481565b600e5481565b60025481565b60095481565b60035481565b610f31612a34565b610f77610f4f610f4085612161565b8661218d90919063ffffffff16565b610f6984610f5b6121c6565b61218d90919063ffffffff16565b6120f590919063ffffffff16565b90506000610fb1308684604051602001610f9393929190613a13565b6040516020818303038152906040528051906020012060001c61222e565b9050838114610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec90613cb7565b60405180910390fd5b6000856040516020016110089190613e37565b60405160208183030381529060405280519060200120905061102981610c4b565b15611069576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106090613bd7565b60405180910390fd5b856011600083815260200190815260200160002060006002811061108957fe5b6002020160008201518160000155602082015181600101559050506110ac6121c6565b601160008381526020019081526020016000206001600281106110cb57fe5b6002020160008201518160000155602082015181600101559050506001600b5401600b81905550505050505050565b611102612a07565b61110a612a07565b60008360405160200161111d9190613e37565b60405160208183030381529060405280519060200120905060106000828152602001908152602001600020600280602002604051908101604052809291906000905b8282101561119b57838260020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061115f565b50505050925060116000828152602001908152602001600020600280602002604051908101604052809291906000905b828210156112075783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906111cb565b50505050915050915091565b60606000826040516020016112289190613e37565b604051602081830303815290604052805190602001209050601560008281526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112e75780601f106112bc576101008083540402835291602001916112e7565b820191906000526020600020905b8154815290600101906020018083116112ca57829003601f168201915b5050505050915050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611382576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137990613cd7565b60405180910390fd5b8060098190555050565b600a5481565b600f5481565b60126020528060005260406000206000915090505481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5481565b60006113e585612093565b905060006002546001548302816113f857fe5b0490506114088787878787612261565b600081111561152b57601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b815260040161148e9291906139ea565b602060405180830381600087803b1580156114a857600080fd5b505af11580156114bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e09190612e3a565b61151f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151690613d77565b60405180910390fd5b80600c5401600c819055505b601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338385036040518363ffffffff1660e01b815260040161158a9291906139ea565b602060405180830381600087803b1580156115a457600080fd5b505af11580156115b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115dc9190612e3a565b61161b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161290613c97565b60405180910390fd5b50505050505050565b63ffffffff81565b60085481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116b790613c57565b60405180910390fd5b8060088190555050565b60005a905060008451905060608167ffffffffffffffff811180156116ee57600080fd5b5060405190808252806020026020018201604052801561172857816020015b611715612a34565b81526020019060019003908161170d5790505b50905060608267ffffffffffffffff8111801561174457600080fd5b5060405190808252806020026020018201604052801561177e57816020015b61176b612a34565b8152602001906001900390816117635790505b509050828951146117c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117bb90613b97565b60405180910390fd5b60005b83811015611aa55760008882815181106117dd57fe5b60200260200101516040516020016117f59190613e37565b60405160208183030381529060405280519060200120905061181681610c4b565b611855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184c90613d57565b60405180910390fd5b61185e81612703565b611866612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b828210156118cc578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190611890565b5050505090506119098c84815181106118e157fe5b6020026020010151826000600281106118f657fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060006002811061192857fe5b6002020160008201518160000155602082015181600101559050506119678b8260016002811061195457fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060016002811061198657fe5b60020201600082015181600001556020820151816001015590505060106000838152602001908152602001600020600280602002604051908101604052809291906000905b82821015611a075783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906119cb565b505050509050611a448c8481518110611a1c57fe5b602002602001015182600060028110611a3157fe5b60200201516120f590919063ffffffff16565b858481518110611a5057fe5b6020026020010181905250611a7f8b82600160028110611a6c57fe5b60200201516120f590919063ffffffff16565b848481518110611a8b57fe5b6020026020010181905250505080806001019150506117c7565b50600086604051602001611ab99190613e37565b60405160208183030381529060405280519060200120905060005b601380549050811015611b48578160138281548110611aef57fe5b90600052602060002001541415611b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3290613c37565b60405180910390fd5b8080600101915050611ad4565b506013819080600181540180825580915050600190039060005260206000200160009091909190915055600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d2d5e70a84848d8d8d6014548e8e6040518963ffffffff1660e01b8152600401611bdd989796959493929190613ab8565b60206040518083038186803b158015611bf557600080fd5b505afa158015611c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2d9190612e3a565b611c6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6390613cf7565b60405180910390fd5b60005a8603905060003a600454600354840281611c8557fe5b040290506000811115611d485780341015611cd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ccc90613bf7565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d3b573d6000803e3d6000fd5b5080600d5401600d819055505b3373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051600060405180830381858888f19350505050158015611d90573d6000803e3d6000fd5b507f9b814ae8a45a4c40d4c60ffa92e0c4b76dec41407cb28b43df9daffa3685f9ac8a604051611dc09190613a96565b60405180910390a1505050505050505050505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5b90613bb7565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b63ffffffff8211158015611ec3575063ffffffff82600a540111155b611f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef990613c77565b60405180910390fd5b81600a6000828254019250508190555081600e600082825401925050819055506001600f60008282540192505081905550600083604051602001611f469190613e37565b604051602081830303815290604052805190602001209050611f6781610c4b565b611fa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f9d90613d57565b60405180910390fd5b611faf81612703565b611fb7612a34565b60116000838152602001908152602001600020600060028110611fd657fe5b600202016040518060400160405290816000820154815260200160018201548152505090506120276120188561200a6121c6565b61218d90919063ffffffff16565b826120f590919063ffffffff16565b9050806011600084815260200190815260200160002060006002811061204957fe5b6002020160008201518160000155602082015181600101559050508260156000848152602001908152602001600020908051906020019061208b929190612a81565b505050505050565b6000816000111580156120aa575063ffffffff8211155b6120e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e090613db7565b60405180910390fd5b60095482029050919050565b6120fd612a34565b6040518351815260208401516020820152825160408201526020830151606082015260408260808360065afa61213257600080fd5b5092915050565b600081600001518360000151148015612159575081602001518360200151145b905092915050565b6000817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001039050919050565b612195612a34565b604051835181526020840151602082015282604082015260408260608360075afa6121bf57600080fd5b5092915050565b6121ce612a34565b60405180604001604052807f077da99d806abd13c9f15ece5398525119d11e11e9836b2ee7d23f6159ad87d460001b81526020017f01485efa927f2ad41bff567eec88f32fb0a0f706588b4e41a8d587d008b7f87560001b815250905090565b60007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001828161225957fe5b069050919050565b83600a5410156122a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161229d90613d17565b60405180910390fd5b83600a600082825403925050819055506000856040516020016122c99190613e37565b6040516020818303038152906040528051906020012090506122ea81610c4b565b612329576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232090613d57565b60405180910390fd5b61233281612703565b61233a612a07565b60116000838152602001908152602001600020600280602002604051908101604052809291906000905b828210156123a0578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612364565b5050505090506123eb6123cb6123b588612161565b6123bd6121c6565b61218d90919063ffffffff16565b826000600281106123d857fe5b60200201516120f590919063ffffffff16565b6011600084815260200190815260200160002060006002811061240a57fe5b60020201600082015181600001556020820151816001015590505060106000838152602001908152602001600020600280602002604051908101604052809291906000905b8282101561248b57838260020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061244f565b5050505090506124d66124b66124a088612161565b6124a86121c6565b61218d90919063ffffffff16565b826000600281106124c357fe5b60200201516120f590919063ffffffff16565b816000600281106124e357fe5b60200201819052506000856040516020016124fe9190613e37565b60405160208183030381529060405280519060200120905060005b60138054905081101561258d57816013828154811061253457fe5b90600052602060002001541415612580576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257790613c37565b60405180910390fd5b8080600101915050612519565b506013819080600181540180825580915050600190039060005260206000200160009091909190915055836015600085815260200190815260200160002090805190602001906125de929190612a81565b50600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391d16ac88360006002811061262a57fe5b60200201518460016002811061263c57fe5b60200201518b6014548b338c6040518863ffffffff1660e01b815260040161266a9796959493929190613e52565b60206040518083038186803b15801561268257600080fd5b505afa158015612696573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ba9190612e3a565b6126f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f090613df7565b60405180910390fd5b5050505050505050565b600080600854141561272257600754438161271a57fe5b04905061277c565b6001600854141561274057600754428161273857fe5b04905061277b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161277290613e17565b60405180910390fd5b5b80601260008481526020019081526020016000205410156129e35761279f612a54565b604051806040016040528060106000868152602001908152602001600020600280602002604051908101604052809291906000905b828210156128105783826002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906127d4565b50505050815260200160116000868152602001908152602001600020600280602002604051908101604052809291906000905b8282101561287f578382600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612843565b5050505081525090506128df8160016002811061289857fe5b60200201516000600281106128a957fe5b6020020151826000600281106128bb57fe5b60200201516000600281106128cc57fe5b60200201516120f590919063ffffffff16565b601060008581526020019081526020016000206000600281106128fe57fe5b6002020160008201518160000155602082015181600101559050506129708160016002811061292957fe5b602002015160016002811061293a57fe5b60200201518260006002811061294c57fe5b602002015160016002811061295d57fe5b60200201516120f590919063ffffffff16565b6010600085815260200190815260200160002060016002811061298f57fe5b6002020160008201518160000155602082015181600101559050506011600084815260200190815260200160002060006129c99190612b01565b816012600085815260200190815260200160002081905550505b806014541015612a03578060148190555060136000612a029190612b2c565b5b5050565b60405180604001604052806002905b612a1e612a34565b815260200190600190039081612a165790505090565b604051806040016040528060008019168152602001600080191681525090565b60405180604001604052806002905b612a6b612a07565b815260200190600190039081612a635790505090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612ac257805160ff1916838001178555612af0565b82800160010185558215612af0579182015b82811115612aef578251825591602001919060010190612ad4565b5b509050612afd9190612b4d565b5090565b5060008082016000905560018201600090555060020160008082016000905560018201600090555050565b5080546000825590600052602060002090810190612b4a9190612b6a565b50565b5b80821115612b66576000816000905550600101612b4e565b5090565b5b80821115612b83576000816000905550600101612b6b565b5090565b600081359050612b968161412b565b92915050565b600082601f830112612bad57600080fd5b8135612bc0612bbb82613f13565b613ee6565b91508181835260208401935060208101905083856040840282011115612be557600080fd5b60005b83811015612c155781612bfb8882612c9d565b845260208401935060408301925050600181019050612be8565b5050505092915050565b600081519050612c2e81614142565b92915050565b600081359050612c4381614159565b92915050565b600082601f830112612c5a57600080fd5b8135612c6d612c6882613f3b565b613ee6565b91508082526020830160208301858383011115612c8957600080fd5b612c948382846140d8565b50505092915050565b600060408284031215612caf57600080fd5b612cb96040613ee6565b90506000612cc984828501612c34565b6000830152506020612cdd84828501612c34565b60208301525092915050565b600081359050612cf881614170565b92915050565b600060208284031215612d1057600080fd5b6000612d1e84828501612b87565b91505092915050565b600080600080600060e08688031215612d3f57600080fd5b600086013567ffffffffffffffff811115612d5957600080fd5b612d6588828901612b9c565b9550506020612d7688828901612c9d565b945050606086013567ffffffffffffffff811115612d9357600080fd5b612d9f88828901612b9c565b9350506080612db088828901612c9d565b92505060c086013567ffffffffffffffff811115612dcd57600080fd5b612dd988828901612c49565b9150509295509295909350565b60008060408385031215612df957600080fd5b600083013567ffffffffffffffff811115612e1357600080fd5b612e1f85828601612b9c565b9250506020612e3085828601612ce9565b9150509250929050565b600060208284031215612e4c57600080fd5b6000612e5a84828501612c1f565b91505092915050565b600060208284031215612e7557600080fd5b6000612e8384828501612c34565b91505092915050565b600060408284031215612e9e57600080fd5b6000612eac84828501612c9d565b91505092915050565b600080600060808486031215612eca57600080fd5b6000612ed886828701612c9d565b9350506040612ee986828701612ce9565b925050606084013567ffffffffffffffff811115612f0657600080fd5b612f1286828701612c49565b9150509250925092565b600080600080600060e08688031215612f3457600080fd5b6000612f4288828901612c9d565b9550506040612f5388828901612ce9565b9450506060612f6488828901612c9d565b93505060a086013567ffffffffffffffff811115612f8157600080fd5b612f8d88828901612c49565b92505060c086013567ffffffffffffffff811115612faa57600080fd5b612fb688828901612c49565b9150509295509295909350565b600080600060808486031215612fd857600080fd5b6000612fe686828701612c9d565b9350506040612ff786828701612ce9565b925050606061300886828701612ce9565b9150509250925092565b60006020828403121561302457600080fd5b600061303284828501612ce9565b91505092915050565b6000806040838503121561304e57600080fd5b600061305c85828601612ce9565b925050602061306d85828601612ce9565b9150509250929050565b60006130838383613132565b60808301905092915050565b600061309b838361392b565b60408301905092915050565b6130b0816140a2565b82525050565b6130bf81614050565b82525050565b6130ce8161403e565b82525050565b60006130df82613f91565b6130e98185613fe4565b93506130f483613f67565b8060005b8381101561312557815161310c8882613077565b975061311783613fbd565b9250506001810190506130f8565b5085935050505092915050565b61313b81613f9c565b6131458184613ff5565b925061315082613f77565b8060005b83811015613181578151613168878261308f565b965061317383613fca565b925050600181019050613154565b505050505050565b61319281613f9c565b61319c8184614000565b92506131a782613f77565b8060005b838110156131d85781516131bf878261308f565b96506131ca83613fca565b9250506001810190506131ab565b505050505050565b60006131eb82613fa7565b6131f5818561400b565b935061320083613f81565b8060005b83811015613231578151613218888261308f565b975061322383613fd7565b925050600181019050613204565b5085935050505092915050565b61324781614062565b82525050565b6132568161406e565b82525050565b600061326782613fb2565b613271818561401c565b93506132818185602086016140e7565b61328a8161411a565b840191505092915050565b60006132a2601c8361402d565b91507f496e707574206172726179206c656e677468206d69736d6174636821000000006000830152602082019050919050565b60006132e260308361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765206167656e63792e000000000000000000000000000000006020830152604082019050919050565b6000613348601b8361402d565b91507f4163636f756e7420616c726561647920726567697374657265642100000000006000830152602082019050919050565b600061338860328361402d565b91507f4e6f7420656e6f756768206665652073656e742077697468207468652074726160008301527f6e73666572207472616e73616374696f6e2e00000000000000000000000000006020830152604082019050919050565b60006133ee60368361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e67652065706f6368206c656e6774682e000000000000000000006020830152604082019050919050565b600061345460138361402d565b91507f4e6f6e636520616c7265616479207365656e21000000000000000000000000006000830152602082019050919050565b600061349460348361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e67652065706f636820626173652e0000000000000000000000006020830152604082019050919050565b60006134fa60288361402d565b91507f46756e642070757368657320636f6e74726163742070617374206d6178696d7560008301527f6d2076616c75652e0000000000000000000000000000000000000000000000006020830152604082019050919050565b600061356060188361402d565b91507f4661696c20746f207472616e7366657220746f6b656e732e00000000000000006000830152602082019050919050565b60006135a0601f8361402d565b91507f496e76616c696420726567697374726174696f6e207369676e617475726521006000830152602082019050919050565b60006135e0602e8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e676520756e69742e0000000000000000000000000000000000006020830152604082019050919050565b600061364660238361402d565b91507f5472616e736665722070726f6f6620766572696669636174696f6e206661696c60008301527f65642100000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006136ac601c8361402d565b91507f4275726e206661696c73207468652073616e69747920636865636b2e000000006000830152602082019050919050565b60006136ec603f8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765207472616e73666572206665652073747261746567792e006020830152604082019050919050565b6000613752601b8361402d565b91507f4163636f756e74206e6f742079657420726567697374657265642e00000000006000830152602082019050919050565b600061379260138361402d565b91507f4661696c20746f20636861726765206665652e000000000000000000000000006000830152602082019050919050565b60006137d2601d8361402d565b91507f4e617469766520277472616e7366657246726f6d27206661696c65642e0000006000830152602082019050919050565b600061381260138361402d565b91507f416d6f756e74206f7574206f662072616e6765000000000000000000000000006000830152602082019050919050565b6000613852603b8361402d565b91507f5065726d697373696f6e2064656e6965643a204f6e6c792061646d696e20636160008301527f6e206368616e6765206275726e206665652073747261746567792e00000000006020830152604082019050919050565b60006138b8601f8361402d565b91507f4275726e2070726f6f6620766572696669636174696f6e206661696c656421006000830152602082019050919050565b60006138f860138361402d565b91507f496e76616c69642065706f636820626173652e000000000000000000000000006000830152602082019050919050565b604082016000820151613941600085018261324d565b506020820151613954602085018261324d565b50505050565b604082016000820151613970600085018261324d565b506020820151613983602085018261324d565b50505050565b61399281614098565b82525050565b60006020820190506139ad60008301846130b6565b92915050565b60006060820190506139c860008301866130a7565b6139d560208301856130c5565b6139e26040830184613989565b949350505050565b60006040820190506139ff60008301856130a7565b613a0c6020830184613989565b9392505050565b600060a082019050613a2860008301866130c5565b613a35602083018561395a565b613a42606083018461395a565b949350505050565b60006020820190508181036000830152613a6481846130d4565b905092915050565b600061010082019050613a826000830185613189565b613a8f6080830184613189565b9392505050565b60006020820190508181036000830152613ab081846131e0565b905092915050565b6000610140820190508181036000830152613ad3818b6131e0565b90508181036020830152613ae7818a6131e0565b90508181036040830152613afb81896131e0565b9050613b0a606083018861395a565b81810360a0830152613b1c81876131e0565b9050613b2b60c0830186613989565b613b3860e083018561395a565b818103610120830152613b4b818461325c565b90509998505050505050505050565b6000602082019050613b6f600083018461323e565b92915050565b60006020820190508181036000830152613b8f818461325c565b905092915050565b60006020820190508181036000830152613bb081613295565b9050919050565b60006020820190508181036000830152613bd0816132d5565b9050919050565b60006020820190508181036000830152613bf08161333b565b9050919050565b60006020820190508181036000830152613c108161337b565b9050919050565b60006020820190508181036000830152613c30816133e1565b9050919050565b60006020820190508181036000830152613c5081613447565b9050919050565b60006020820190508181036000830152613c7081613487565b9050919050565b60006020820190508181036000830152613c90816134ed565b9050919050565b60006020820190508181036000830152613cb081613553565b9050919050565b60006020820190508181036000830152613cd081613593565b9050919050565b60006020820190508181036000830152613cf0816135d3565b9050919050565b60006020820190508181036000830152613d1081613639565b9050919050565b60006020820190508181036000830152613d308161369f565b9050919050565b60006020820190508181036000830152613d50816136df565b9050919050565b60006020820190508181036000830152613d7081613745565b9050919050565b60006020820190508181036000830152613d9081613785565b9050919050565b60006020820190508181036000830152613db0816137c5565b9050919050565b60006020820190508181036000830152613dd081613805565b9050919050565b60006020820190508181036000830152613df081613845565b9050919050565b60006020820190508181036000830152613e10816138ab565b9050919050565b60006020820190508181036000830152613e30816138eb565b9050919050565b6000604082019050613e4c600083018461395a565b92915050565b600061016082019050613e68600083018a61395a565b613e75604083018961395a565b613e82608083018861395a565b613e8f60c0830187613989565b613e9c60e083018661395a565b613eaa6101208301856130a7565b818103610140830152613ebd818461325c565b905098975050505050505050565b6000602082019050613ee06000830184613989565b92915050565b6000604051905081810181811067ffffffffffffffff82111715613f0957600080fd5b8060405250919050565b600067ffffffffffffffff821115613f2a57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115613f5257600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050919050565b6000819050602082019050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600061404982614078565b9050919050565b600061405b82614078565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006140ad826140b4565b9050919050565b60006140bf826140c6565b9050919050565b60006140d182614078565b9050919050565b82818337600083830152505050565b60005b838110156141055780820151818401526020810190506140ea565b83811115614114576000848401525b50505050565b6000601f19601f8301169050919050565b61413481614050565b811461413f57600080fd5b50565b61414b81614062565b811461415657600080fd5b50565b6141628161406e565b811461416d57600080fd5b50565b61417981614098565b811461418457600080fd5b5056fea264697066735822122056695844caa0f1ebe5998444fb454f3d0114d09e71859029212c139d916547d464736f6c634300060c00330000000000000000000000004cfbbdfbd5bf0814472ff35c72717bd095ada055000000000000000000000000076010bfc6377b24d10545e69840c9a6b79d6471000000000000000000000000d3a56c7fd5493268d299a4111a1b493c95b0b56900000000000000000000000000000000000000000000000000005af3107a4000

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://56695844caa0f1ebe5998444fb454f3d0114d09e71859029212c139d916547d4
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.