Token Triple Confirmation

Overview ERC20

Price
$0.00 @ 0.000000 AVAX
Fully Diluted Market Cap
Total Supply:
142,000,000 TC

Holders:
7 addresses

Transfers:
-

Loading
[ Download CSV Export  ] 
Loading
[ Download CSV Export  ] 
Loading

OVERVIEW

Triple Confirmation provides a non-custodial, automated trading platform built on Avalanche and other EVM-compatible blockchains. Only depositors can withdraw their funds. Our strategies execute via smart contracts with all tokens kept on-chain, allowing anyone to retrieve their funds at any time.


Update? Click here to update the token ICO / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
TC

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 4200000 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-04-22
*/

// SPDX-License-Identifier: WTFPL


// = = = = = = = = = = = = = = = = = //
//                                   //
//   Written by Triple Confirmation  //
//                                   //
//           20 April 2023           //
// = = = = = = = = = = = = = = = = = //


pragma solidity ^0.8.19;


/**
 * @dev OpenZeppelin's IERC20 interface with `value` -> `amount`
 */
interface IERC20 {

    // ### VIEW FUNCTIONS ###
    function name() external view returns (string memory name);

    function symbol() external view returns (string memory symbol);

    function decimals() external view returns (uint8 decimals);

    function totalSupply() external view returns (uint totalSupply);




    // ### CONTRACT INTERACTIONS ###
    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint balance);

    /**
     * @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 to, uint amount) external returns (bool success);

    /**
     * @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 (uint allowance);

    /**
     * @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, uint amount) external returns (bool success);

    /**
     * @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 from, address to, uint amount) external returns (bool success);




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

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

}




/**
 * @dev
 * File level variables are compiled into the contract as constant uints.
 * This method of variable management helps to reduce bytecode size while
 * reducing the likelihood of mistakes. Rather than writing out the exact
 * index or static numbers, we opt for referencing these file level constants
 * thereby making any adjustments immediate and ubiquitous across the entire
 * contract code. Having a central registry for constant numbers ensures
 * consistency across the codebase and is therefore good code management.
 */

/**
 * @dev Indices related to `allowances` and the `approve()` system.
 */
uint8 constant lenAMem = 4; // needs to include `aTimeRemaining`
uint8 constant lenAStor = 3;
uint8 constant aAllowance = 0;
uint8 constant aTimestamp = 1;
uint8 constant aPerpetual = 2;
uint8 constant aTimeRemaining = 3;

/**
 * @dev
 * All `uint8 constant` variables below at the file level are index identifiers
 * allowing certain variables to be grouped together in arrays for easier
 * storage, recall, mutability, and recursion.
 */
uint8 constant rAmount = 0;
uint8 constant rAccountsToRain = 1;

/**
 * @dev Indices related to the `delegationMem` pseudo-struct mapping.
 */
uint8 constant lenDelegationMem = 4;
uint8 constant encodedDelegation = 0;
uint8 constant startIndex = 1;
uint8 constant total = 2;
uint8 constant excluded = 3;

/**
 * @dev
 * Indices related to recall of `bytes32` encodes of
 * supported Delegation `functionName`s given by a
 * user to identify the function delegated.
 */
uint8 constant lenDelegates = 5;
uint8 constant dFuncSetId = 0;
uint8 constant dFuncTransferMultiple = 1;
uint8 constant dFuncRain = 2;
uint8 constant dFuncRainList = 3;
uint8 constant dFuncRainAll = 4;

/**
 * @dev Indices related to the `errors` array of `string`s.
 */
uint8 constant lenErrors = 34;
uint8 constant errSymbol = 0;
uint8 constant errAdminAuth = 1;
uint8 constant errTreasuryAdminAuth = 2;
uint8 constant errGuardianTreasuryAdminAuth = 3;
uint8 constant errInsufficientBalance = 4;
uint8 constant errTransferContract = 5;
uint8 constant errInsufficientAllowance = 6;
uint8 constant errTransferMultiple = 7;
uint8 constant errList = 8;
uint8 constant errDelegateSetId = 9;
uint8 constant errSetId = 10;
uint8 constant errSetIdProtected = 11;
uint8 constant errSetAdmin0 = 12;
uint8 constant errSetAdmin1 = 13;
uint8 constant errSetTreasury0 = 14;
uint8 constant errSetTreasury1 = 15;
uint8 constant errSetGasPerLoop = 16;
uint8 constant errSetGasValues = 17;
uint8 constant errSetBreakAtGasThres = 18;
uint8 constant errSetRainMinBalance = 19;
uint8 constant errPermit0 = 20;
uint8 constant errPermitDeadline = 21;
uint8 constant errPermitBadSig = 22;
uint8 constant errGasPerLoopHeader = 23;
uint8 constant errGasPerLoop = 24;
uint8 constant errRainAmounts = 25;
uint8 constant errRainNumAccounts = 26;
uint8 constant errRunMyDelegation = 27;
uint8 constant errAuthMyDelegation = 28;
uint8 constant errDelegationDoesntMatch = 29;
uint8 constant errInvalidDelegation = 30;
uint8 constant errClaimERC20 = 31;
uint8 constant errDecreaseAllowance = 32;
uint8 constant errSetAllowanceTimeToLive = 33;

/**
 * @dev 
 * `__denominator` is copied to `denominator` in the TokenBase.
 * We opted to hardcode the `decimals` as 10 ** 6 to allow for
 * use in assembly{} operations.
 */
uint constant __denominator = 1000000;
uint constant __denominatorBy10 = __denominator / 10;
uint constant __maxRainThreshold = 4200690000;
uint constant __minSecsAllowanceTimeToLive = 30;
string constant __strPeriod = ".";
string constant __strZero = "0";

/**
 * @notice
 * Disconnected library for deployment in a Web3xx VM such as in the
 * Remix IDE to allow us to easily harvest a array of error
 * strings to copy into TokenBase via repeated `setError()` executions.
 * This methodology doesn't import bytecode on construction and saves
 * an immense amount of bytecode compared to including the errors in
 * the TokenBase contract itself.
 */
abstract contract TokenBaseUtils {

    // ### UTILITY FUNCTIONS ###
    function _isContract(address _account) internal view returns (bool) {
        /**
         * @dev
         * According to EIP-1052, 0x0 is the value returned
         * for not-yet-created accounts and
         * 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
         * is returned for accounts without code such as `keccak256('')`.
         */
        bytes32 _codehash;
        bytes32 _accountHash =
            0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        
        assembly { _codehash := extcodehash(_account) }

        /**
         * @dev
         * Return true if the `_account` in question has both:
         *   # Been created, AND
         *   # Is an address with bytecode.
         */
        return _codehash != _accountHash && _codehash != 0x0;
    }

    /**
     * @return -> Raw number without consideration to decimal places.
     */
    function __uintToString(
        uint __value
    ) internal pure returns (
        string memory
    ) {
        // Save gas and return a constant string of "0" if the `_value` == 0.
        if (__value == 0) {
            return __strZero;
        }
        uint __temp = __value;
        uint __digits;
        while (__temp != 0) {
            ++__digits;
            __temp /= 10;
        }
        bytes memory __buffer = new bytes(__digits);
        while (__value != 0) {
            __buffer[--__digits] = bytes1(uint8(48 + uint(__value % 10)));
            __value /= 10;
        }

        return string(__buffer);
    }
    
    /**
     * @notice
     * `_divisor` is safely set to 1 if 0 is given in order to avoid
     * division-by-0 errors. Division by 1 is highly likely to
     * be the desired outcome since that simply returns the same
     * number as before the division operation. `divisor`s other
     * than 0 can be returned as-is without change since we only
     * need to protect against returning a 0 `_divisor`. Less than 0
     * `_divisor`s are impossible to return since `uint`s are
     * by definition always 0 or positive.
     */
    function _safeDivision(uint _divisor) internal pure returns (uint) {
        if (_divisor == 0) {
            return 1;
        }
        return _divisor;
    }

    /**
     * @dev Converts a `uint` to its ASCII `string` decimal representation.
     * @param _value -> Any number which the user desires to convert into `string`.
     * @return -> Nicely formatted string output WITH decimal places.
     */
    function _uintToString(
        uint _value
    ) internal pure returns (
        string memory
    ) {
        // Save gas and return a constant string of "0" if the `_value` == 0.
        if (_value == 0) {
            return __strZero;
        }
        /**
         * @dev
         * We need to use assembly to achieve a proper,
         * non-overflowing modulo.
         */
        uint _decimalToShow;
        assembly { _decimalToShow := mod(_value, __denominator) }

        /**
         * @dev
         * Next generate the decimals string,
         * fixed to the number of `decimalToShow`.
         */
        string memory _strDecimals = __uintToString(_decimalToShow);

        /**
         * @dev
         * Continue adding padded 0's to the beginning of the `strDecimals`
         * until the desired number of `decimalsToShow` is achieved.
         * If we didn't do this, then an expected output of
         * 1234.0056 would be outputted as 1234.56.
         */
        if (_decimalToShow > 0) {
            for (; _decimalToShow < __denominatorBy10; _decimalToShow *= 10) {
                _strDecimals = string.concat(__strZero, _strDecimals);
            }
        }

        // Before returning, assemble the string.
        return string.concat(
            __uintToString(_value / __denominator),
            __strPeriod,
            _strDecimals
        );
    }
}

/**
 * @dev
 * Got a strange error message from Etherscan about this being imported
 * when it's very clearly not. This library definitely isn't included
 * in TokenBase but is derivative and very much related, hence why
 * it's included in this source file. We'll leave uncommented for now
 * and simply re-comment if Snowtrace/Etherscan refuses to compile
 * and verify the bytecode after mainnet deployment.
 */
contract TokenBaseErrors is TokenBaseUtils {
    /**
     * @return _errors -> Formatted for recursively passing into `setError()`.
     * @dev Throw into Remix IDE to copy-paste the generated Errors.
     */
    function generateErrors(
        string calldata _symbol
    ) external pure returns (
        string[lenErrors] memory _errors
    ) {
        string memory __symbol = string.concat(" ", _symbol, ".");
        _errors = [
            "",
            "AUTH: Sender must be the Admin Wallet.",
            "AUTH: Sender must be either the Treasury Wallet or the Admin Wallet.",
            "AUTH: Sender must be the Guardian Wallet, the Treasury Wallet, or the Admin Wallet.",
            "TRANSFER: Insufficient balance: ",
            "TRANSFER: Use `transferFrom()` to transfer tokens to a smart contract.",
            "TRANSFER-FROM: Insufficient `approve()` amount remaining: ",
            "TRANSFER-MULTIPLE: Count of recipients and amounts must be identical.",
            "LIST: First index cannot be greater than the last index.",
            "DELEGATE SET-ID: Count of recipients and amounts must be identical.",
            "SET: `id` disallowed for `account`.",
            "SET: `id` is protected.",
            "SET: New Admin Wallet cannot be set to a null address.",
            "SET: New Admin Wallet cannot be the same as the current one.",
            "SET: New Treasury Wallet cannot be set to a null address.",
            "SET: New Treasury Wallet cannot be the same as the current one.",
            "SET: `gasPerLoop` cannot be greater than 1/20 the `block.gaslimit`.",
            "SET: `breakAtGasThreshold` must be a greater value than `gasPerLoop`.",
            "SET: `breakAtGasThreshold` cannot be greater than 1/4 the `block.gaslimit`.",
            string.concat(
                "SET: Maximum possible value of ",
                _uintToString(__maxRainThreshold),
                __symbol
            ),
            "PERMIT ERROR: The 0 address cannot permit others.",
            "PERMIT ERROR: Expired deadline.",
            "PERMIT ERROR: Invalid signature.",
            "GAS: Submit with ",
            "",
            "RAIN: Invalid `amounts` provided.",
            "RAIN: Must rain on at least 1 account.",
            "DELEGATION: Null address are disallowed from execution.",
            "DELEGATION: You're not the delegate or owner.",
            "DELEGATION: No match found.",
            "DELEGATION: Unsupported function.",
            "CLAIM ERC-20: Failed transfer.",
            "DECREASE ALLOWANCE: Amount to deduct is greater than existing `approve()` amount: ",
            string.concat(
                "APPROVE DEADLINE: Minimum possible value is ",
                __uintToString(__minSecsAllowanceTimeToLive),
                " seconds. ",
                "Maximum possible value is 2^248."
            )
        ];

        for (uint8 i; i < lenErrors; ++i) {
            _errors[i] = string.concat(_symbol, " | ", _errors[i]);
        }

        // Two exceptions in the list.
        _errors[errSymbol] = __symbol;
        delete _errors[errGasPerLoop];
        
        return _errors;
    }
}

/**
 * @notice
 * Everything in this comment box is related to generating the
 * error `string`s for saving during token deployment.
 * 
 * @devnote
 * Outputted `_errors` array ready for use in TokenBase's `constructor()`.
    [
        " TC.",
        "TC | AUTH: Sender must be the Admin Wallet.",
        "TC | AUTH: Sender must be either the Treasury Wallet or the Admin Wallet.",
        "TC | AUTH: Sender must be the Guardian Wallet, the Treasury Wallet, or the Admin Wallet.",
        "TC | TRANSFER: Insufficient balance: ",
        "TC | TRANSFER: Use `transferFrom()` to transfer tokens to a smart contract.",
        "TC | TRANSFER-FROM: Insufficient `approve()` amount remaining: ",
        "TC | TRANSFER-MULTIPLE: Count of recipients and amounts must be identical.",
        "TC | LIST: First index cannot be greater than the last index.",
        "TC | DELEGATE SET-ID: Count of recipients and amounts must be identical.",
        "TC | SET: `id` disallowed for `account`.",
        "TC | SET: `id` is protected.",
        "TC | SET: New Admin Wallet cannot be set to a null address.",
        "TC | SET: New Admin Wallet cannot be the same as the current one.",
        "TC | SET: New Treasury Wallet cannot be set to a null address.",
        "TC | SET: New Treasury Wallet cannot be the same as the current one.",
        "TC | SET: `gasPerLoop` cannot be greater than 1/20 the `block.gaslimit`.",
        "TC | SET: `breakAtGasThreshold` must be a greater value than `gasPerLoop`.",
        "TC | SET: `breakAtGasThreshold` cannot be greater than 1/4 the `block.gaslimit`.",
        "TC | SET: Maximum possible value of 4200.690000 TC.",
        "TC | PERMIT ERROR: The 0 address cannot permit others.",
        "TC | PERMIT ERROR: Expired deadline.",
        "TC | PERMIT ERROR: Invalid signature.",
        "TC | GAS: Submit with ",
        "",
        "TC | RAIN: Invalid `amounts` provided.",
        "TC | RAIN: Must rain on at least 1 account.",
        "TC | DELEGATION: Null address are disallowed from execution.",
        "TC | DELEGATION: You're not the delegate or owner.",
        "TC | DELEGATION: No match found.",
        "TC | DELEGATION: Unsupported function.",
        "TC | CLAIM ERC-20: Failed transfer.",
        "TC | DECREASE ALLOWANCE: Amount to deduct is greater than existing `approve()` amount: ",
        "TC | APPROVE DEADLINE: Minimum possible value is 30 seconds. Maximum possible value is 2^248."
	];
    [
        " TCC.",
        "TCC | AUTH: Sender must be the Admin Wallet.",
        "TCC | AUTH: Sender must be either the Treasury Wallet or the Admin Wallet.",
        "TCC | AUTH: Sender must be the Guardian Wallet, the Treasury Wallet, or the Admin Wallet.",
        "TCC | TRANSFER: Insufficient balance: ",
        "TCC | TRANSFER: Use `transferFrom()` to transfer tokens to a smart contract.",
        "TCC | TRANSFER-FROM: Insufficient `approve()` amount remaining: ",
        "TCC | TRANSFER-MULTIPLE: Count of recipients and amounts must be identical.",
        "TCC | LIST: First index cannot be greater than the last index.",
        "TCC | DELEGATE SET-ID: Count of recipients and amounts must be identical.",
        "TCC | SET: `id` disallowed for `account`.",
        "TCC | SET: `id` is protected.",
        "TCC | SET: New Admin Wallet cannot be set to a null address.",
        "TCC | SET: New Admin Wallet cannot be the same as the current one.",
        "TCC | SET: New Treasury Wallet cannot be set to a null address.",
        "TCC | SET: New Treasury Wallet cannot be the same as the current one.",
        "TCC | SET: `gasPerLoop` cannot be greater than 1/20 the `block.gaslimit`.",
        "TCC | SET: `breakAtGasThreshold` must be a greater value than `gasPerLoop`.",
        "TCC | SET: `breakAtGasThreshold` cannot be greater than 1/4 the `block.gaslimit`.",
        "TCC | SET: Maximum possible value of 4200.690000 TCC.",
        "TCC | PERMIT ERROR: The 0 address cannot permit others.",
        "TCC | PERMIT ERROR: Expired deadline.",
        "TCC | PERMIT ERROR: Invalid signature.",
        "TCC | GAS: Submit with ",
        "",
        "TCC | RAIN: Invalid `amounts` provided.",
        "TCC | RAIN: Must rain on at least 1 account.",
        "TCC | DELEGATION: Null address are disallowed from execution.",
        "TCC | DELEGATION: You're not the delegate or owner.",
        "TCC | DELEGATION: No match found.",
        "TCC | DELEGATION: Unsupported function.",
        "TCC | CLAIM ERC-20: Failed transfer.",
        "TCC | DECREASE ALLOWANCE: Amount to deduct is greater than existing `approve()` amount: ",
        "TCC | APPROVE DEADLINE: Minimum possible value is 30 seconds. Maximum possible value is 2^248."
	];
*/




// ------------------------------------------------------------------------------------ //

/**
 * @title TokenBase for deployment as the "Triple Confirmation" token.
 * @notice This token contract is ERC-20 and EIP-2612 compatible.
 * 
 * @notice
 * The size of this TokenBase contract allows for up to
 * 42,000 optimizsation runs. More runs than this doesn't
 * seem to produce a meaningful difference in the bytecode
 * size and thus likely doesn't help reduce gas costs.
 * The bytecode remains the same at 4.2 billion runs.
 * 
 * @notice
 * When the American spelling of a word may have a 'z'
 * in its suffix, we use 'zs' as a compromise with the
 * British 's' spelling. In other words:
 * "Optimization" + "Optimisation" = "Optimizsation".
 * Our project is based in the UK. Our Solidity devs are American.
 * We find the spelling compromise to be apropos.
 * 
 * @notice
 * Choosing which ERC or EIP standards to support is one of the most
 * research-intensive tasks to perform when writing a token contract.
 * We chose to start with the ubiquitous ERC-20 standard as our base
 * platform and ultimately chose to only augment it with EIP-2612.
 * 
 * @notice
 * We opted not to support ERC-223, ERC-777, EIP-1363, or EIP-3009 for
 * a variety of reasons. Most of all because none of those standards are
 * as widely accepted or expected as ERC-2ying 0 and EIP-2612.
 *   # ERC-223: We were unable to verify the extent of its support amongst
 *              popular DeFi platforms, and it's still in Draft as of 2023.
 *   # ERC-777: Implementation is quite complicated and its verification of
 *              functionality even more so. ERC-777 also has re-entry
 *              complications, most famously with Uniswap.
 *   # EIP-1363: We were unable to verify the extent of its support amongst
 *               popular DeFi platforms.
 *   # EIP-3009: Very similar to EIP-2612 but with the drawback of being
 *               unable to easily burn previously signed `permit()` messages.
 * Considering the adoption of EIP-2612 by Uniswap, USDC, ARB token, and
 * others, we feel the `permit()` gasless approval system is much simpler
 * while largely solving the long-standing concerns regarding `approve()`.
 * 
 * @notice
 * We chose to build on ERC-20 and EIP-2612 with optional automated
 * expiration of `allowance`s. Our automated expiration system is self-built
 * without relying or complying with any particular ERC or EIP standard.
 * Perhaps we will submit our system as an EIP in our attempt to further
 * improve the `approve()` + `transferFrom()` user experience while:
 *   # Complying to the expected ERC-20 standard
 *   # Providing greater security, and
 *   # Offering approachable controls over existing `approve()`s.
 * 
 * @dev
 * Variables are named without any prefix if the function is externally-facing
 * or with appended `_` prefix depending on how many layers deep. For example
 * the `__swapId()` function is itself nested inside the `_swapId()` function
 * but itself also has a nested function inside, thus there also exists
 * a named `___swapId()` function. The only exceptions to this rule are:
 *   # `i` for a counter omits the `_` prefix unless there's multiple counters,
 *   # and when the unprefixed variable name is already exists in global scope
 *     and would thus be shadowed. Example: `account` -> `_account`.
 */
contract TC is IERC20, TokenBaseUtils {
    // ------------------------------------------------------------------ //
    //  ----------------------  GLOBAL VARIABLES  ----------------------  //

    /**
     * @dev
     * We thought that tightly packing unsigned integers into a single
     * 32-byte storage slot (1 word) would be advantageous for bytecode
     * and/or gas efficiency. In our testing it cost both /more/ gas
     * AND /more/ bytecode to use tightly packed integers versus using
     * standard unsigned `uint` which is a full 256 bits and 32 bytes.
     * Originally we had the following initializsed first to tightly pack:
     * uint8 + uint32 + uint32 + uint40 + uint32 only used 0.5625 of a single
     * uint256's 32 bytes. While – per the Ethereum.org documentation – that
     * should've resulted in them all being tightly packed within a
     * single 32-byte storage slot (1 word) and thus using less bytecode
     * and less gas, the reality is the opposite. Using smaller `uint`s than
     * the standard 256 used /more/ bytecode and /more/ gas in all operations.
     * 
     * @notice ERC-20 required variable -> `decimals`
     */
    uint8 public constant decimals = 6;

    /**
     * @dev
     * Equal to 10 ** `decimals`.
     * Assembly compile error requires hard-coded,
     * real value not a computed value such as
     * `= 10 ** decimals` or even `= 10 ** 6`.
     * 
     * @return denominator -> 1000000
     */
    uint public constant denominator = __denominator;

    /**
     * @dev 4,200 TC upper limit for `rain()` minimum balance eligibility.
     */
    uint public rainMinimumBalance = 1 * denominator;

    /**
     * @dev
     * Default is 200% the gas cost of a standard `transfer()` execution.
     * In our testing that's approximately the cost of each loop
     * transferring to multiple accounts in a single Tx.
     */
    uint public gasPerLoop = 31400;
    
    /**
     * @notice breakAtGasThreshold is used in:
     *   # `addAccounts()`
     *   # `updateErrorMsg_GasPerLoop()`
     *   # `_verifyLoopGas()`
     *   # `eraseAllApprovals()`
     *   # `transferMultiple()`
     *   # `rain()`
     *   # `rainList()`
     *   # `rainAll()`
     */
    uint public breakAtGasThreshold = 50000;
    
    /**
     * @dev
     * Immutable is employed to enforce fixed supply tokenomics.
     * `supply` is whole tokens (no decimals).
     * `totalSupply` is ERC-20 required. Raw total token units.
     * 
     * @notice ERC-20 required variable -> `totalSupply`
     */
    uint public immutable supply; // Whole tokens. 
    uint public immutable totalSupply; // Raw total number.

    /**
     * @dev
     * ERC-20 required variables. Immutable.
     * A commented `immutable` keyword for any `string` variable can be
     * interpreted hereafter to mean the variable is indeed set at
     * construction time and never again edited. As of this contract's
     * writing in 2023, the `immutable` keyword does not support `string`s.
     * 
     * @dev
     * Until clarity is found around EIP-2612 about whether the
     * `version` can be a string other than "1" – which is required
     * by EIP-712 – we opt for two different variables:
     *   # `version` -> "1" as required in EIP-712 on which EIP-2612 relies.
     *   # `versionNotes` -> To give information about this deployment.
     * 
     * @notice ERC-20 required variables -> `name` and `symbol`
     */
    string public /* immutable */ name;
    string public /* immutable */ symbol;
    string public constant version = "1"; // Required per EIP-2612 -> EIP-712
    string public constant versionNotes = "2023-04-20 | Final";
    
    /**
     * @dev
     * Events unique to this token contract.
     * Not part of the ERC-20 standard.
     */
    event Mint(address indexed origin, uint amount);
    event TransferMultiple(address indexed account, uint amount);
    event Rain(address indexed gifter, uint amountThisBlock);
    event RainList(address indexed account, uint total);
    event RainAll(address indexed account, uint total);
    event Claimed(address indexed token, uint amount, address indexed receiver);
    event AdminChange(address indexed from, address indexed to);
    event TreasuryChange(address indexed from, address indexed to);

    /**
     * @dev `string` error messages recalled out of storage via named-index.
     * @notice Can be grabbed as a full list via `getErrors()` `view` function.
     */
    string[lenErrors] errors;
    uint public maxRecipientsPerBlock;

    /**
     * @return Give a list of `string` of all `errors`.
     */
    function getErrors() external view returns (string[lenErrors] memory) {
        return errors;
    }

    /**
     * @dev
     * These addresses are primarily established for the purposes of
     * easily identifying and tracking the `treasuryWallet` across
     * the Triple Confirmation system of contracts. The `adminWallet`
     * and `treasuryWallet` both have the same authority level
     * EXCEPT that the `adminWallet` can change the `treasuryWallet` without
     * the latter's permission. Worth noting that while the `adminWallet`
     * can change the `treasuryWallet` address, the `adminWallet`
     * cannot transfer tokens away from the outgoing `treasuryWallet`
     * without being given permission via sufficient `allowance`.
     * 
     * @notice
     * `guardianWallet` is created to assist `adminWallet` with routine
     * token contract management that are of low consequence. These are
     * parameters relating to highly recursive operations such as adjusting
     * error messages or setting team wallets to lower `id`s for easier
     * access and organizsation from `getAccountsList()` calls.
     * 
     * @notice
     * `guardianWallet` is authorizsed by `adminWallet` to run only:
     *   # `setId()`
     *   # `setError()`
     *   # `addAccounts()`
     *   # `setProtected()`
     *   # `setGasPerLoop()`
     */
    address public adminWallet;
    address public treasuryWallet;
    address public guardianWallet;

    /**
     * @return circulatingSupply -> Raw value unsigned integer (uint)
     * of `totalSupply` not under the control of the `adminWallet`
     * or `treasuryWallet`.
     */
    function getCirculatingSupply() external view returns (uint) {
        uint circulatingSupply = totalSupply - balance[adminWallet];

        /**
         * @notice
         * The `circulatingSupply` is the amount of tokens
         * available to all accounts aside from the `adminWallet`
         * and `treasuryWallet`. To get the `circulatingSupply()`
         * we exclude these tokens from the `totalSupply` variable.
         * The difference is the amount "out in the wild."
         */
        if (adminWallet != treasuryWallet) {
            circulatingSupply -= balance[treasuryWallet];
        }

        return circulatingSupply;
    }

    /**
     * @notice
     * Account information.
     * We found the most efficient storage and execution gas costs to come
     * from utilizsing mappings of various primitive variable types as opposed
     * to packing all variables into a struct. Recalling and writing to a
     * struct appeared to cost significantly more gas – especially during
     * `for` loops – in our testing.
     * 
     * @dev
     * - Unique mappings to our token contract:
     *   # `id`
     *   # `account`
     *   # `protected`
     *   # `rainAllNextId`
     *   # `rainAllRunningTotal`
     *   # `allowanceTimeToLive`
     *   # `approvedSpenders`, and the
     *   # `delegationMem`
     * These are all employed to provide:
     *   # An improved `approve()` experience,
     *   # For the execution of `transferMultiple()`,
     *   # Various `rain()` functions, and
     *   # Delegate certain looping transactions thereby allowing users to
     *     employ scripted wallets via Web3xx on their behalf.
     * 
     * @notice
     * The `protected` mapping allows the `adminWallet`, `treasuryWallet`,
     * or `guardianWallet` to lock a specific account to a specific `id`.
     * This potentially enables easier team management of the TC trading bot
     * and any potential rewards related and given out to promote its use.
     * 
     * @dev
     * Be aware the `public` visibility gobbles up bytecode vs `private`.
     * 
     * @dev
     * Largest handle-able `allowanceTimeToLive` value due to the need
     * to add with `block.timestamp`:
     * 115339776388732929035197660848497720713218148788040405586178452820382218977280
     */
    uint public numAccounts;
    mapping(address => uint) public id;
    mapping(uint => address) public account;

    /**
     * @dev
     * We trialed three different systems to store these account-specific values:
     *   # Single mapping of `uint[]` list,
     *   # Struct containing all values, and
     *   # Primitive type mappings (current).
     * The other two methods – a single `uint[]` per address, and a single
     * struct containing all account values – both cost more in bytecode and
     * gas to use. Thus we settled on employing mappings of primitive types.
     */
    mapping(address => uint) balance;
    mapping(address => bool) protected;
    mapping(address => uint) rainAllNextId;
    mapping(address => uint) rainAllRunningTotal;
    mapping(address => uint248) allowanceTimeToLive;
    mapping(address => address[]) approvedSpenders;
    mapping(address => mapping(address => uint[lenAStor])) allowances;
    mapping(address => uint[lenDelegationMem]) delegationMem;
    



    // ------------------------------------------------------------------ //
    //  ------------------------  GET ACCOUNTS  ------------------------  //

    /**
     * @dev
     * The Delegation struct is intended purely for input. Its execution
     * requires verification against an encoded `uint` stored in a
     * given account's `delegationMem` array.
     */
    struct Delegation {
        address delegate;
        string functionName;
        address[] recipients;
        uint[] amounts;
    }

    /**
     * @dev
     * The following structs below here are intended purely for
     * `view` functions including `getAccountsList()`:
     *   # RainStruct
     *   # Approved
     *   # Account
     */
    struct RainStruct {
        bool excluded;
        uint allNextId;
        uint allRunningTotal;
        uint delegation;
    }

    struct Approved {
        address account;
        uint amount;
        uint timestamp;
        uint timeRemaining;
        uint perpetualSince;
    }

    struct Approves {
        uint248 timeToLive;
        Approved[] list;
    }
    
    struct Account {
        uint id;
        address account;
        uint balance;
        bool protected;
        Approves approvedSpenders;
        RainStruct rain;
    }

    /**
     * @notice
     * Converts an account's `address[]` held via `approvedSpenders`
     * to named-value (easier-to-read) `Approved[]` list.
     */
    function _buildApprovedStructList(
        address _account,
        uint248 _allowanceTimeToLive
    ) private view returns (
        Approved[] memory _approvedList
    ) {
        // Pull the account's list of `address` that have been approved.
        address[] memory _approves = approvedSpenders[_account];

        /**
         * @notice
         * We like lots of info about approvedSpenders. Hence there's a
         * whole struct list dedicated to them. First grab how
         * many approved spenders exist for this account. Then we'll
         * start building the struct list.
         */
        uint _numApproved = _approves.length;

        // Create an empty Approved struct list with the length identified above.
        _approvedList = new Approved[](_numApproved);

        // Loop through the empty Approved struct list and fill in
        // each approved address, including the amount and deadline.
        for (uint i; i < _numApproved; ++i) {

            // Grab the approved account at index `i` of the 
            // address list obtained via the `approvedSpenders` mapping.
            address _spender = _approves[i];

            /**
             * @dev
             * Grab the `allowances` out of storage setting the current
             * `allowance` to the proper index (0 which == `aAllowance`)
             * and then continue building the approve struct.
             */
            uint[lenAMem] memory _allowance =
                _calcAllowance(
                    _account,
                    _spender,
                    _allowanceTimeToLive
                );

            /**
             * @dev
             * If the `_spender` still has an `allowance` of `_account`,
             * then give the actual time remaining to expiration. Otherwise
             * if the `_spender` has been set to perpetual then the
             * time remaining will be 0 but the `allowance` amount
             * will persist.
             * 
             * @dev
             * Save data about this particular account to the
             * appropriate index `i` in the Approved struct list.
             */
            _approvedList[i] = Approved(
                _spender,
                _allowance[aAllowance],
                _allowance[aTimestamp],
                _allowance[aTimeRemaining],
                _allowance[aPerpetual]
            );
        }

        return _approvedList;
    }

    /**
     * @notice
     * Converts an account's mappings related to `rain()` and its two
     * derivative functions – `rainList()` and `rainAll()` – to a more
     * understandable named-value `RainStruct[]` list.
     */
    function _buildRainStruct(
        address _account
    ) private view returns (RainStruct memory) {
        return RainStruct(
            _isContract(_account),
            rainAllNextId[_account],
            rainAllRunningTotal[_account],
            delegationMem[_account][encodedDelegation]
        );
    }

    /**
     * @param _first -> First `id` of which to grab account information.
     * @param _last -> Last `id` of which to grab account information.
     * @return _accounts -> List of all accounts and their associated information.
     */
    function _accountsList(
        uint _first,
        uint _last
    ) private view returns (
        Account[] memory _accounts
    ) {
        _accounts = new Account[](1 + _last - _first);
        uint _i;

        // Loop over each account.
        for (uint i = _first; i <= _last; ++i) {
            /**
             * @dev
             * Build out the Account struct including the Approved[] list
             * and the RainStruct[] list. We use nested structs for easier
             * named-value reading on the Web3xx side.
             * 
             * @notice
             * We employ a separate counter `_i` distinct from `i`
             * to fill in the `accounts` without worrying about
             * underflow, overflow, or out-of-index errors.
             * This `_i` counter is incremented by 1 after retrieval
             * from memory via the `++` suffix. Appending the `++`
             * as a prefix would instead increment by 1 before retrieval
             * which is not what we want, hence we append `++` as a suffix.
             * 
             * @dev
             * Incrementing variables by 1 with the `++` as a prefix uses
             * less gas than incrementing by 1 with the `++` as a suffix.
             * For `view` functions there exists no functional gas limit
             * since we can always spin up our own node with no timeout.
             */
            _accounts[_i++] = getAccount(account[i]);
        }

        return _accounts;
    }

    /**
     * @notice
     * External `view` wrapper to obtain a list of all accounts.
     * Costs around ≈ 20,000 gas per account meaning there's a
     * soft limit of ≈ 395 accounts supported by a gas-limited node.
     * 
     * @notice
     * If there's no accounts, this will revert. We find this to be
     * an acceptable limitation.
     */
    function getAccountsList() external view returns (Account[] memory) {
        return _accountsList(1, numAccounts);
    }

    /**
     * @notice
     * The same as above but with the added option of grabbing accounts only
     * between certain indices/values of `id`.
     * 
     * @param first -> In reference to `id` NOT `getAccountsList()` indices.
     * @param last  -> In reference to `id` NOT `getAccountsList()` indices.
     * 
     * @notice
     * Submitting a larger number than `numAccounts` for `first` will force the
     * list to /start/ at the last account.
     * Submitting a larger number than `numAccounts` for `last` will force the
     * list to /terminate/ at the last account.
     */
    function getAccountsListByIds(
        uint first,
        uint last
    ) external view returns (
        Account[] memory
    ) {
        require(
            first <= last,
            errors[errList]
        );

        /**
         * @dev
         * Purposefully omit the `0` index since that's a null user that
         * should always result in default, unset values.
         */
        if (last > numAccounts) {
            last = numAccounts;
            if (first > numAccounts) {
                first = numAccounts;
            }
        }
        return _accountsList(first, last);
    }

    /**
     * @param _account -> Provide all relevant associated information.
     */
    function getAccount(
        address _account
    ) public view returns (
        Account memory
    ) {
        uint248 _allowanceTimeToLive = allowanceTimeToLive[_account];
        return Account(
            id[_account],
            _account,
            balance[_account],
            protected[_account],
            Approves(
                _allowanceTimeToLive,
                _buildApprovedStructList(_account, _allowanceTimeToLive)
            ),
            _buildRainStruct(_account)
        );
    }

    /**
     * @param _id -> Provide all relevant account info on account at `_id`.
     */
    function getAccountById(
        uint _id
    ) external view returns (
        Account memory
    ) {
        return getAccount(account[_id]);
    }




    // ------------------------------------------------------------------ //
    //  -------------------------  CONSTRUCTOR  ------------------------  //

    /**
     * @dev Constructor.
     * @param _deployer -> Address employed to disburse tokens.
     * @param _guardian -> Address entrusted to be Guardian.
     * @notice ERC-20 required variables -> `_name` and `_symbol` and `_supply`.
     */
    constructor(
        string memory _name,
        string memory _symbol,
        uint _supply,
        address _deployer,
        address _guardian
    ) {
        name                = _name;
        symbol              = _symbol;
        supply              = _supply;
        totalSupply         = _supply * denominator;
        adminWallet         = msg.sender;
        treasuryWallet      = msg.sender;
        balance[_deployer]  = totalSupply;
        guardianWallet      = _guardian;

        /**
         * @dev
         * We purposefully do not add the `msg.sender`
         * or `_deployer` because neither the deploying
         * wallet nor the deployer should be remembered. 
        _addAccount(msg.sender);
         */
        emit Transfer(address(0), _deployer, totalSupply);
        emit Mint(_deployer, totalSupply);
        
        /**
         * @dev
         * Domain creation MUST occur either
         * after the storage of `name` or
         * not during the `constructor()`.
         */
        saveDomainSeparatorAndChainId();
    }




    // ------------------------------------------------------------------ //
    //  -----------------  ADMIN-GUARDIAN HOUSEKEEPING  ----------------  //

    /**
     * @notice
     * `adminWallet`, `treasuryWallet`, and `guardianWallet` are all unique
     * address slots that may be three unique entities. A situation can arise
     * where they do not see eye-to-eye on certain housekeeping duties such as
     * what a specific error message should read. In the case of a dispute, the
     * `adminWallet` is endowed with full credentials to strip the other two
     * of their authority and has the exclusive ability to arbitrate any and
     * all issues.
     */

    /**
     * @dev
     * We tried setting the errors in the `constructor()` but that would cost
     * too much gas to deploy. We then tried to set all the strings in a single
     * function here but that added +0.3Kb to the bytecode. Instead, we've
     * chosen to implement the `guardianWallet` and allow it to loop over the
     * entire `errors` storage array to set each error one-at-a-time.
     *
    function setErrorList(
        string[lenErrors] calldata _errors
    ) external _adminTreasuryOrGuardianAuth {
        assert(id[msg.sender] == 0);
        for (uint8 i; i < lenErrors; ++i) {
            errors[i] = _errors[i];
        }
    }
    */

    /**
     * @notice Accepts a given `string` and sets it to the `index` in `errors`.
     */
    function setError(
        string calldata _error,
        uint index
    ) external _adminTreasuryOrGuardianAuth {
        assert(index < lenErrors);
        errors[index] = _error;
    }

    /**
     * @dev Costs ≈ 85,000 gas per account.
     * @param accounts -> List of address to add as new accounts.
     * @param shouldBeProtected -> Attribute of `protected` for each given address.
     * @notice `accounts` and `shouldBeProtected` must be identical in length
     * and index-matched to each other. Entries should be linked by index.
     * @dev Increases bytecode by +0.1Kb to make a nested private exec function.
     */
    function addAccounts(
        address[] calldata accounts,
        bool[] calldata shouldBeProtected
    ) external _adminTreasuryOrGuardianAuth {

        uint _end = accounts.length;
        assert(_end == shouldBeProtected.length);
        _verifyLoopGas(_end / 2);

        for (uint i; i < _end; ++i) {
            if (_hasInsufficientGasRemaining() && i > 0 && i + 1 < _end) {
                return;
            }
            _addAccount(accounts[i]);
            protected[accounts[i]] = shouldBeProtected[i];
        }
    }

    /**
     * @notice
     * Allows certain wallets to remain at a static `id`.
     * 
     * @notice
     * Set `address(0)` as a protected wallet to disable accounts
     * from being automatically erased during `rain()` functions.
     * 
     * @notice
     * Be aware that setting the account at the current
     * `numAccounts` will also (temporarily) prevent accounts
     * from being erased during `rain()` functions until a
     * new un`protected` account joins.
     */
    function setProtected(
        address wallet,
        bool shouldBeProtected
    ) external _adminTreasuryOrGuardianAuth {
        protected[wallet] = shouldBeProtected;
    }
    
    /**
     * @notice
     * Very minor exploits while running `rainAll()` with a mischievous
     * `adminWallet`, `treasuryWallet`, or `guardianWallet`:
     *   # --> Set an already-rained-on `id` to a not-yet-rained `_id`.
     * 
     * @notice
     * The above could result in a given account getting rained on two or more
     * times during `rainAll()` and disallowing someone else from being rained
     * on at all. This minor exploit can advantage certain accounts while
     * disadvantaging others and can be employed by third-parties who have
     * sway over any of the aforementioned administrative wallets without the
     * need to be one themselves. Ultimately what's most important is being
     * aware of this concern. This is a social issue, not an actual bug.
     * 
     * @dev
     * Swapping the account at `id` == 0 which is expected to be a null account
     * of `address(0)` is intended to be avoided in all scenarios.
     */
    function setId(address _account, uint _id) external _adminTreasuryOrGuardianAuth {
        require(
            !protected[account[_id]],
            errors[errSetIdProtected]
        );
        _setId(_account, _id);
    }

    /**
     * @dev
     * Updating error strings with complex `string.concat()` logic eats up a
     * lot of bytecode. This particular one we find to be important since
     * requiring the `guardianWallet`, `treasuryWallet`, or `adminWallet` to
     * push a separate `setError()` transaction in addition to a
     * `setGasPerLoop()` transaction doesn't seem very well-conceived. This way
     * only the aforementioned `setGasPerLoop()` function need be called and
     * its associated error message will automatically be updated with all the
     * new values as calculated with the new `gasPerLoop` parameter.
     */
    function updateErrorMsg_gasPerLoop() external {
        // Saves a little bytecode using a nested, private execution function.
        _updateErrorMsg_gasPerLoop();
    }




    // ------------------------------------------------------------------ //
    //  --------  INTERNAL ADMIN-GUARDIAN HOUSEKEEPING HELPERS  --------  //

    /**
     * @dev Nested private execution function required for delegation use.
     * @param _account -> Set its `id` to `_id`.
     * @param _id -> Submit `0` to attempt to delete the `_account`.
     */
    function _setId(address _account, uint _id) private {
        /**
         * @dev
         * We want to ensure the `_account` is a current account
         * so we run it through `_addAccount()` to verify its
         * registration or to register it in the case that it's
         * not yet an account of this token contract. If the
         * `_account` wasn't registered then we could accidentally
         * `__swapId()` with an unset entry which would result
         * in `address(0)` being registered. We want to avoid that
         * behaviour and we also want to only `__swapId()`s with
         * registered non-null accounts, hence we run `_account`
         * through `_addAccount()`.
         */
        require(
            /**
             * @dev
             * Only allow the `__swapId()` to take place if the `_account` is
             * registered. If the `_account` has an `id` of 0 after the
             * `_addAccount` – such as if `address(0)` is submitted as the
             * `_account` – then the `require()` below will fail.
             */
            _addAccount(_account) > 0
            &&
            (
                (
                    /**
                     * @dev
                     * Only process a deletion if:
                     *   # The `_account`s `balance` is 0, AND
                     *   # The deletion was requested from `_id` == 0.
                     */
                    balance[_account] == 0
                    && _id == 0
                )
                || // OR
                (   
                    /**
                     * @dev
                     * Otherwise only allow the `__swapId()`
                     * if the `_id` requested is less than
                     * or equal to the `numAccounts` as
                     * swapping outside of that would result
                     * in `address(0)` becoming registered.
                     * We do not want `address(0)` to ever
                     * be registered.
                     */
                    _id > 0
                    && _id <= numAccounts
                )
            ),
            errors[errSetId]
        );

        // Process the `id` swap.
        __swapId(_account, _id);
    }

    /**
     * @dev
     * Execute the actual swap of `_id`.
     * Do NOT call directly without verification
     * and `require()` checks beforehand.
     */
    function ___swapId(address _account, uint _id) private {
        (
            account[_id],
            account[id[_account]],
            id[_account],
            id[account[_id]]
        )
        =
        (
            account[id[_account]],
            account[_id],
            id[account[_id]],
            id[_account]
        );
    }

    /**
     * @dev Call from the `_setId()` private function.
     */
    function __swapId(address _account, uint _id) private {
        /**
         * @dev
         * If the wallet existing in the requested `_id`
         * is `protected` then do nothing. In order to
         * supplant that account, set its `id` to something
         * else or eliminate its `protected` attribute.
         * 
         * @notice
         * To prevent any account from being erased, set
         * `address(0)` to `protected` == true.
         */
        if (protected[account[_id]]) { return; }

        // Delete the account.
        if (_id == 0) {
            /**
             * @dev If the wallet is `protected` then do nothing.
             */
            if (protected[_account]) { return; }

            /**
             * @dev
             * Execute the deletion by swapping the `_account`
             * to the end of the list of `id`s. Then delete
             * the `_account`s `id` link keeping in mind to
             * increment `numAccounts` down by 1 afterwards.
             */
            ___swapId(_account, numAccounts);
            delete account[numAccounts--];
            delete id[_account];

            return;
        }
        /**
         * @dev
         * Note that we don't recursively verify that the account on the
         * receiving end of swap with `_account` is themselves ineligible for
         * deletion; such as having a 0 balance. Our intention is that should
         * the `adminWallet`, `treasuryWallet`, or `guardianWallet` desire to
         * cleanse the `rain()` list of 0 balance wallets, then they will loop
         * over all accounts with `_id` set to 0 and thus over time and many
         * swaps, reach the desired outcome of pruning ineligible accounts.
         * 
         * Performing a simple swap of ID's this way without recursive
         * verification allows MetaMask and other Web3 providers to better
         * estimate the gas cost of the transaction, and ensures the cost of
         * any given `rain()` function isn't overly bloated by the calls to
         * this `_swapId()` function which itself is nested inside the
         * `_hasRainMinimumBalance()` function which is nested inside the
         * `rain()` functions.
         * 
         * Our philosophy is to enable pruning of the accounts list in a
         * cost-effective manner, and to spread out such pruning over multiple
         * transactions by a somewhat random number of balance-holders.
         */
        ___swapId(_account, _id);
    }

    /**
     * @dev Private executable to update the `gasPerLoop` error message.
     */
    function _updateErrorMsg_gasPerLoop() private {
        maxRecipientsPerBlock = 
            (block.gaslimit - breakAtGasThreshold)
            / _safeDivision(gasPerLoop);
        
        errors[errGasPerLoop] =
            string.concat(
                " gas. Required: ",
                __uintToString(gasPerLoop),
                " gas/recipient + ",
                __uintToString(breakAtGasThreshold),
                " gas/Tx. ",
                __uintToString(maxRecipientsPerBlock),
                " max recipients."
            );
    }




    // ------------------------------------------------------------------ //
    //  ------------------  AUTHORIZSATION MODIFIERS  ------------------  //

    /**
     * @notice
     * Authorizsation is inherited such that `adminWallet` has full privileges,
     * `treasuryWallet` has a subset of those privileges, and `guardianWallet`
     * has a subset of `treasuryWallet`s privileges. Thus there is nothing
     * that `guardianWallet` can do that `treasuryWallet` cannot, and nothing
     * that `treasuryWallet` can do that `adminWallet` cannot.
     */

    function _walletIsAdmin(address _wallet) private view returns (bool) {
        return _wallet == adminWallet;
    }

    modifier _adminAuth() {
        require(
            _walletIsAdmin(msg.sender),
            errors[errAdminAuth]
        );
        _;
    }

    function _walletIsTreasury(address _wallet) private view returns (bool) {
        return _wallet == treasuryWallet;
    }
    
    function _walletIsTreasuryOrAdmin(address _wallet) private view returns (bool) {
        return _walletIsTreasury(_wallet) || _walletIsAdmin(_wallet);
    }
    
    modifier _adminOrTreasuryAuth() {
        require(
            _walletIsTreasuryOrAdmin(msg.sender),
            errors[errTreasuryAdminAuth]
        );
        _;
    }

    function _walletIsGuardian(address _wallet) private view returns (bool) {
        return _wallet == guardianWallet;
    }

    function _walletIsGuardianTreasuryOrAdmin(address _wallet) private view returns (bool) {
        return _walletIsGuardian(_wallet) || _walletIsTreasuryOrAdmin(_wallet);
    }

    modifier _adminTreasuryOrGuardianAuth() {
        require(
            _walletIsGuardianTreasuryOrAdmin(msg.sender),
            errors[errGuardianTreasuryAdminAuth]
        );
        _;
    }




    // ------------------------------------------------------------------ //
    //  ----------------------  INTERNAL HELPERS  ----------------------  //

    function _hasInsufficientGasRemaining() private view returns (bool) {
        return breakAtGasThreshold > gasleft();
    }

    /**
     * @notice
     * Accounts who have a `balance` below the `rainMinimumBalance`
     * are deemed ineligible for `rain()` and `rainAll()` functions.
     * Since `rain()` operates on a random basis and `rainAll()`
     * operates on an all-accounts basis, we feel it makes sense to
     * set a low threshold above which an account's `balance` must land
     * in order to qualify. This functionality is invisible to senders.
     * Senders do not specific who they `rain()` or `rainAll()`, thus
     * we feel this functionality is fair to ensure tokens stay in
     * circulation – something very important for fixed supply
     * tokenomics – and to encourage accounts to hold a `balance`
     * thereby putting positive pressure on tokenomics. We also want to
     * keep gas costs reasonable while looping across many accounts. That's
     * only possible if set the threshold at such an amount that account
     * pollution doesn't occur; that is, we want to avoid people making
     * hundreds of accounts each with TC dust for the exclusive purpose of
     * reaping higher `rainAll()` rewards and a higher probability of
     * `rain()` rewards. The `rainMinimumBalance` is adjustable for that
     * very purpose: For the administrative team to discourage account
     * pollution while ensuring the fun execution of `rain()` functions.
     * 
     * @notice
     * `rainList()` is explicitly exempted from the aforementioned `balance`
     * checks because if the sender provides a list to rain on then we can
     * logically assume the sender does intend and want to rain on each
     * address. If we did perform the same check on `rainList()` executions,
     * senders could very well become confused upon realizsing only
     * certain accounts received their rain while others in their list
     * did not. Without the ability to notify the sender of why certain
     * accounts were rained and others weren't, senders will simply
     * become frustrated at this obtuse functionality.
     * 
     * @notice
     * `protected` wallets are excluded from being rained on – except in the
     * case of `rainList()` which bypasses the check – to avoid abuse by the
     * `adminWallet`, `treasuryWallet`, or `guardianWallet` setting their
     * personal wallets earlier in the `id` list and thus being more likely to
     * be hit in `rainAll()` executions than if they had a higher `id`. Should
     * the administrative wallets set their personal wallets to a lower `id`
     * and /not/ set them as `protected`, we feel the requirement to have
     * `rainMinimumBalance` to be sufficiently fair despite the slight
     * advantage gained by being earlier in the `rainAll()` list. Furthermore,
     * this minor advantage is limited to `rainAll()` exclusively.
     */
    function _execRain(
        address _owner,
        address _recipient,
        uint _amount
    ) private returns (
        bool _skip
    ) {

        if (
            /**
             * @dev
             * Don't process the rain if:
             *   # The same account raining is the one chosen to be rained on
             *   # The `_recipient` is protected
             *   # A null address is hit.
             */
            _owner == _recipient
            || protected[_recipient]
            || _isNullAccount(_recipient) // Specifically avoid `_addAccount()`.
        ) {
            return _skip;
        }

        /**
         * @dev
         * Only if the `_recipient`s balance is 0 AND the `rainMinimumBalance`
         * is greater than 0 should accounts be eligible for deletion.
         * The deletion will be skipped if an account is `protected`.
         * Note though the flow of if{} statements prevents `protected`
         * accounts from reaching this logic block.
         */
        uint _recipientBal = balance[_recipient];
        if (_recipientBal == 0 && rainMinimumBalance > 0) {
            __swapId(_recipient, 0); // Delete the account.
            return _skip;
        }

        /**
         * @dev
         * Massively cheaper in gas costs to verify a given address
         * is a contract each time versus saving and recalling
         * a `bool` held in storage.
         */
        if (_isContract(_recipient)) {
            return _skip;
        }

        /**
         * @dev
         * Reaching this logic block means the account is deemed eligible
         * to receive `rain()`ed tokens. Process a direct `_transfer()`.
         */
        if (_recipientBal >= rainMinimumBalance) {
            return _transfer(_owner, _recipient, _amount);
        }
        
        /**
         * @dev For all other conditions, skip the account.
         */
        return _skip;
    }

    /**
     * @dev
     * In order to implement a successful `rain()` function,
     * we need to store a list of all accounts. This list is
     * used and verified in `rain()` and `rainAll()` with
     * 0 balance accounts pruned unless `rainMinimumBalance`
     * is also set to 0.
     * 
     * @return _id -> Lookup of `_newAccount` in the `id` mapping.
     * @dev For null accounts, `_id` should always return 0.
     */
    function _addAccount(address _newAccount) private returns (uint _id) {
        _id = id[_newAccount];
        if (_id > 0 || _isNullAccount(_newAccount)) {
            return _id;
        }

        /**
         * @dev
         * By incrementing `numAccounts` before setting
         * it in the `account` mapping we ensure that
         * `id` == 0 is also address(0). This is the
         * intended output since otherwise address(0)
         * would be eligible for `rain()` and would thus
         * burn tokens. We would much prefer to avoid
         * burning tokens since we have a fixed supply
         * and would rather manage the circulating supply
         * via the trading bot and its associated fees.
         */
        _id = ++numAccounts;
        account[_id] = _newAccount;
        id[_newAccount] = _id;
        return _id;
    }

    /**
     * @return -> String with `_owner`s balance included.
     */
    function _insufficientBalanceError(
        address _owner
    ) private view returns (
        string memory
    ) {
        return string.concat(
            errors[errInsufficientBalance],
            _tokenValueAsString(balance[_owner])
        );
    }

    /**
     * @return -> String of `_value` in decimal form with `symbol` appended.
     */
    function _tokenValueAsString(
        uint _value
    ) private view returns (
        string memory
    ) {
        return string.concat(
            _uintToString(_value),
            errors[errSymbol]
        );
    }

    /**
     * @notice
     * Nested `require()`s that verify the `sender` has a sufficient
     * `balance` to send the `totalRainAmount` tokens. The error
     * message is generated on-demand in a human-readable and
     * intuitively-understandable format with decimals shown.
     * 
     * @notice
     * Named `_rainAndListChecks()` because this check applies
     * only to `rain()` and `rainList()`.
     * 
     * @param _enforceGasRequired -> Should be true if actually executing.
     */
    function _rainAndListChecks(
        address _owner,
        uint _amount,
        uint _accountsToRain,
        bool _enforceGasRequired
    ) private view {
        /**
         * @notice
         * Our intention is that only those who have an insufficient `balance`
         * pay extra gas for the error message to be generated. We feel
         * the need to return an easily understood error message to be
         * important for a good user experience when attempting to `rain()`.
         */
        require(
            balance[_owner] >= _amount * _accountsToRain,
            /**
             * @notice
             * If the `sender` has an insufficient `balance`,
             * tell them how many tokens they must have in
             * order to run the function { `rain()` | `rainList()` }
             * they desire.
             */
            string.concat(
                _insufficientBalanceError(_owner),
                " Required: ",
                _tokenValueAsString(_amount * _accountsToRain)
            )
        );

        /**
         * @dev
         * While raining on 0 accounts would not present any execution
         * issues, we feel the user experience is improved having a
         * revert occur with a clear error message that no `rain()`
         * took place.
         */
        require(
            _accountsToRain > 0,
            errors[errRainNumAccounts]
        );

        /**
         * @notice Parameter to optionally verify the submitted gas.
         */
        if (_enforceGasRequired) {
            _verifyLoopGas(_accountsToRain);
        }
    }

    /**
     * @notice Ensure sufficient gas was given to run at least one loop.
     * 
     * @dev
     * We could limit `_loops` to `maxRecipientsPerBlock` but decide that's
     * not as important or as guaranteed a check as directly limiting the
     * maximum amount of `_gasRequired` to 90% the `block.gaslimit` which
     * will always be possible to submit.
     */
    function _verifyLoopGas(uint _loops) private view {
        /**
         * @dev
         * Ensure the `_gasRequired` isn't greater than 90% the `block.gaslimit`
         * otherwise a user may be unable to submit the given transaction. The
         * safest path to ensure this check doesn't return a value greater than
         * or too close to the `block.gaslimit` is to simply limit it after the
         * calculated `_gasRequired`. We want to ensure the requirement here is
         * some amount of gas that a user can reasonably produce. Thus, limit
         * the upper bound of `_gasRequired` to 90% the `block.gaslimit`. The
         * `++` prefix on `_loops` assists in ensuring sufficient gas is given
         * to run at least one loop before the `breakAtGasThreshold` is hit.
         */
        uint _gasRequired = breakAtGasThreshold + (gasPerLoop * ++_loops);
        if (_gasRequired > 90 * block.gaslimit / 100) {
            _gasRequired = 90 * block.gaslimit / 100;
        }

        /**
         * @dev
         * If there is insufficient `gasleft()` then error with a message
         * explaining how much gas needs to be provided.
         */
        require(
            gasleft() > _gasRequired,
            string.concat(
                errors[errGasPerLoopHeader],
                __uintToString(_gasRequired),
                errors[errGasPerLoop]
            )
        );
    }




    // ------------------------------------------------------------------ //
    //  -------------------  INTERNAL ERC-20 HELPERS  ------------------  //

    /**
     * @return Is the `_account` one of the null wallets, or (this) address?
     * 
     * @notice
     * In order of likelihood to occur.
     * Prevent token burns by silently
     * re-routing to the `treasuryWallet`.
     */
    function _isNullAccount(address _account) private view returns (bool) {
        // These are all eligible via `transferFrom()`.
        return
            _account == address(0)
            || _account == address(0xdead)
            || _account == address(this);
    }

    /**
     * @notice
     * Our assumption is that if someone sends tokens to this token contract
     * or to one of the above listed null accounts, they are intending to burn
     * them or get rid of them forever. Should they have transferred a mistake
     * then there exists the (social) potential for the `treasuryWallet` to
     * send the tokens back to their rightful owner.
     * 
     * @dev Executes the requested balance transfer and emits the {Transfer} event.
     * @notice ERC-20 required execution function.
     */
    function _transfer(
        address _from,
        address _to,
        uint _amount
    ) private returns (
        bool
    ) {
        require(
            balance[_from] >= _amount,
            _insufficientBalanceError(_from)
        );

        /**
         * @notice Redirect lost tokens to the `treasuryWallet`.
         * No reason to spend add'l gas adding `_from` accounts.
         */
        if (_addAccount(_to) == 0 || _isNullAccount(_from)) {
            _to = treasuryWallet;
        }

        /**
         * @dev Execute the `balance` transfer.
         */
        balance[_from] -= _amount;
        balance[_to] += _amount;

        emit Transfer(_from, _to, _amount);
        return true;
    }

    /**
     * @notice
     * By simply setting an `allowance` to a static `_amount`, there exists a
     * race condition exploit native to the ERC-20 standard where a `_spender`
     * can spend both the previous `allowance` AND this new `allowance` amount
     * being set. We attempt to nullify this race condition exploit inherent
     * to the ERC-20 standard by implementing EIP-2612 and its `permit()`
     * function. EIP-2612 adds support for gasless approvals and allows the
     * `allowance` to be set just before `transferFrom()` execution all in the
     * same transaction in the same block. If executed this way, two problems
     * are simultaneously solved:
     *   # Race condition for double `allowance` spend, and
     *   # Need to submit two transactions { `approve()` + `transferFrom()` }
     *     and spend 50% more gas. This has systemic drawbacks as well since
     *     a single, simple transfer costs twice as much blockchain bandwidth,
     *     filling up crucial block space.
     * 
     * @dev
     * Current blockchain technology is inherently throughput-restricted.
     * We feel a better system than the two transaction ERC-20 standard can
     * be implemented to transfer tokens to a dApp or smart contract. While
     * ERC-223, ERC-777, EIP-1363, and EIP-3009 all offer unique proposal,
     * we found EIP-2612 to be the most compelling due to its simplicity
     * and clear support across 1/3 of the top tokens, by market cap, in 2023.
     * 
     * @dev
     * This function is the endpoint of:
     *   # `approve()`
     *   # `increaseAllowance()`
     *   # `decreaseAllowance()`
     *   # `permit()`
     *
     * @notice ERC-20 and EIP-2612 required private execution function.
     */
    function _approve(
        address _owner,
        address _spender,
        uint _amount
    ) private returns (
        bool
    ) {
        /**
         * @dev
         * Standard ERC-20: `approve()` sets the `aAllowance` amount
         * in our `allowances` `uint[3]` mapping.
         */
        allowances[_owner][_spender][aAllowance] = _amount;

        /**
         * @dev
         * Save the `_spender` into the `_owner`s `approvedSpenders` list if
         * they're a new spender. The `approvedSpenders` list and all associated
         * `allowances` can be deleted via `eraseAllApprovals()` with
         * `onlyExpired` set to false.
         * 
         * @dev
         * The same address can be pushed into the `approvedSpenders` list twice
         * if the `aTimestamp` of a given spender's allowance is reset to 0
         * without first erasing the entire `approvedSpenders` list. Each address
         * in the `approvedSpenders` list for a given `_owner` should appear
         * only once. When queried via the `getAccount()` or its derivative
         * functions, each `_spender` in the `approvedSpenders` list should
         * appear with all relevant info including that `_spender`s `allowance`,
         * when it was last updated, and how many seconds it has until expiration.
         * We try to avoid duplicative entries in the `approvedSpenders` list
         * by not erasing the `aTimestamp` except when an `_owner` requests
         * a full `eraseAllApprovals()` with `onlyExpired` set to false.
         */
        if (allowances[_owner][_spender][aTimestamp] == 0) {
            approvedSpenders[_owner].push(_spender);
        }

        // Non-standard ERC-20: Remember when the `allowances` was set.
        allowances[_owner][_spender][aTimestamp] = block.timestamp;
        
        /**
         * @dev
         * Finalizse the `approve()` by emitting the {Approval} event
         * and returning true as required by the ERC-20 standard.
         */
        emit Approval(_owner, _spender, _amount);
        return true;
    }

    /**
     * @notice
     * Give the list of recipients the amount in the `_amounts` list
     * using the index as a link between the two. The lists
     * must be of identical length to avoid unintended transfers.
     * 
     * @notice ERC-20 extended internal execution function.
     */
    function _transferMultiple(
        address _owner,
        bool _delegated,
        address[] calldata _recipients,
        uint[] calldata _amounts
    ) private {
        uint _end = _recipients.length;
        _verifyLoopGas(_end);

        // Local variable setup.
        uint i;
        if (_delegated) { i = delegationMem[_owner][startIndex]; }
        uint _start = i;
        uint _total; // Sum of all transfers.

        // Loop through `_recipients` list.
        for (; i < _end; ++i) {
            if (
                _delegated
                && _hasInsufficientGasRemaining()
                && i > _start
                && i + 1 < _end
            ) {
                break;
            }

            /**
             * @notice
             * No verification of if the `recipient` is a
             * smart contract where tokens may be irreversibly lost.
             */
            _transfer(_owner, _recipients[i], _amounts[i]);

            /**
             * @dev
             * Must sum the individual amounts for an accurate total.
             * Can't multiply by `amount` because each recipient might
             * receive a different amount.
             */
            _total += _amounts[i];
        }

        if (_delegated) {
            delegationMem[_owner][total] += _total;
            delegationMem[_owner][startIndex] = i;
        }

        if (i >= _recipients.length) {
            emit TransferMultiple(
                _owner,
                _delegated
                    ? delegationMem[_owner][total]
                    : _total
            );
        }
    }

    /**
     * @dev
     * Private executable to calculate the `allowance` taking into consideration
     * the `_owner`s set duration until expiration of `_spender`s `allowance`.
     */
    function _calcAllowance(
        address _owner,
        address _spender,
        uint248 _allowanceTimeToLive
    ) private view returns (
        uint[lenAMem] memory _allowances
    ) {
        /**
         * @dev
         * Grab and remember the `allowances` out of storage.
         * This doesn't cost any less gas than individual calls
         * but does help in centralizse the `allowance` calculation
         * logic and to return a fully set array of values for
         * easy parsing and management across the token contract.
         * The array itself is used most heavily in the `getAccount(s)`
         * functions. The first indexed value is the calculated
         * `allowance` taking into consideration the aforementioned
         * spoil/expiration time.
         */
        for (uint8 i; i < lenAStor; ++i) {
            _allowances[i] = allowances[_owner][_spender][i];
        }

        /**
         * @dev
         * 1 second added to allow an `allowance` to be used if the current time
         * and the `_deadline` are the same time. Thus transferring if the
         * current time is exactly `_deadline` is accepted but transferring one
         * second /after/ the `_deadline` is rejected. While we could use `>=`
         * here, when returned via the `getAccount()` or its derivative
         * functions the owner would see 0 seconds remaining when the
         * `allowance` really has 1 second remaining until expiration.
         */
        uint _deadline = 1 + _allowanceTimeToLive + _allowances[aTimestamp];
        if (_deadline > block.timestamp) {
            _allowances[aTimeRemaining] = _deadline - block.timestamp;
        }

        /**
         * @dev
         * If {
         *  the user has set an `allowanceTimeToLive`
         *  AND
         *  the user has NOT set this `_spender` to perpetual
         *  AND
         *  the `allowance` has zero time remaining,
         * }
         * THEN
         * Return a 0 `allowance` by deleting the appropriate entry.
         * Note that `delete` REFUNDS some gas whereas `= 0` COSTS add'l gas.
         */
        if (
            _allowanceTimeToLive > 0
            &&
            _allowances[aPerpetual] == 0
            &&
            _allowances[aTimeRemaining] == 0
        ) {
            delete _allowances[aAllowance];
        }

        return _allowances;
    }

    /**
     * @dev Private executable to loop through revoking approvals.
     */
    function _eraseAllApprovals(
        bool _onlyExpired,
        uint248 _allowanceTimeToLive
    ) private returns (
        bool _completed
    ) {
        address[] memory _approves = approvedSpenders[msg.sender];
        _verifyLoopGas(3 * _approves.length / 2); // 150% the expense of `rain()`
        
        /**
         * @dev `_revokeApproval()` will return false if the Tx ran out of gas.
         */
        for (uint i; i < _approves.length; ++i) {
            if (!_revokeApproval(_approves[i], _onlyExpired, _allowanceTimeToLive)) {
                return _completed; // false
            }
        }

        _completed = true;

        // Full revokes should also delete the `approvedSpenders` list.
        if (!_onlyExpired) {
            delete approvedSpenders[msg.sender];
        }

        return _completed;
    }

    /**
     * @dev Private executable to revoke an approval of one `_spender` only.
     */
    function _revokeApproval(
        address _spender,
        bool _onlyExpired,
        uint248 _allowanceTimeToLive
    ) private returns (
        bool _completed
    ) {
        // Returning to save progress is preferable to reverting.
        if (_hasInsufficientGasRemaining()) {
            return _completed; // false
        }

        _completed = true;

        /**
         * @dev
         * We thought we could save gas by calling the `_allowances[]`
         * array once out of storage rather than calling individual
         * values. Apparently Solidity charges a storage recall
         * /per index/ meaning grabbing a whole array is significantly
         * more expensive than calls of individual values as needed, provided
         * we don't call the same value out of storage more than once.
        uint[lenA] memory _allowances = _calcAllowance(msg.sender, _spender);
         */

        /**
         * @dev
         * If the `allowance` is still active – that is, has not expired –
         * and `onlyExpired` is true, then don't delete this `allowance`.
         */
        if (_onlyExpired) {

            /**
             * @dev
             * If the `allowance` is still active, leave it alone
             * and continue through the list of `approvedSpenders`. This
             * is because the sender desires only to destroy
             * `onlyExpired` approvals.
             * 
             * @dev
             * If the `allowance` is perpetual with the sender having
             * explicitly having set the `_spender` as perpetual (having
             * no expiration date), then `continue` through the list.
             */
            if (
                allowances[msg.sender][_spender][aPerpetual] > 0
                // `calcAllowance()` is higher in gas to calculate, hence second.
                || _calcAllowance(
                    msg.sender,
                    _spender,
                    _allowanceTimeToLive
                )[aAllowance] > 0
            ) {
                return _completed; // true
            }

            /**
             * @dev
             * Otherwise if the `_spender` has 0 allowance AND
             * was not previously registered by the sender as
             * having no expiration date then delete the allowance.
             */
            delete allowances[msg.sender][_spender][aAllowance];
            return _completed; // true
        }

        /**
         * @dev
         * If not `onlyExpired` then the sender desires to destroy
         * all data related to their `allowances`.
         */
        delete allowances[msg.sender][_spender];
        return _completed; // true
    }




    // ------------------------------------------------------------------ //
    //  --------------------------  SETTERS  ---------------------------  //

    /**
     * @dev
     * Private executable for changing the `adminWallet` and/or `treasuryWallet`.
     * Saves bytecode to combine the functionality into a private exec function.
     */
    function _execAdminTreasuryWalletChange(
        address _newWallet,
        address _existingWallet,
        bool _transferTokens,
        string[2] memory _errors
    ) private {
        require(
            _addAccount(_newWallet) > 0,
            _errors[0] // Invalid, null address.
        );

        require(
            _newWallet != _existingWallet,
            _errors[1] // No change in address.
        );

        if (_transferTokens) {
            // Enforces `allowance` if `adminWallet` != `treasuryWallet`.
            transferFrom(
                _existingWallet,
                _newWallet,
                balance[_existingWallet]
            );
        }

        // Safest security measure is to erase stored Delegation.
        delete delegationMem[_existingWallet];
        delete delegationMem[_newWallet];
    }
    
    /**
     * @notice Only the `adminWallet` can replace itself and set a successor.
     */
    function setAdminWallet(
        address newAdminWallet,
        bool transferTokens
    ) external _adminAuth {
        _execAdminTreasuryWalletChange(
            newAdminWallet,
            adminWallet,
            transferTokens,
            [errors[errSetAdmin0], errors[errSetAdmin1]]
        );

        /**
         * @notice
         * Outgoing `adminWallet` can choose to allow the incoming `adminWallet`
         * to inherit its `balance` or not.
         */
        if (adminWallet == treasuryWallet) {
            setTreasuryWallet(newAdminWallet, transferTokens);
        }
        
        emit AdminChange(adminWallet, newAdminWallet);
        adminWallet = newAdminWallet;
    }

    /**
     * @notice By default the `treasuryWallet` is set to the `adminWallet`.
     * 
     * @notice
     * `transferFrom()` is used instead of `_transfer()` because otherwise
     * an exploit exists where the `adminWallet` can `setTreasuryWallet()`
     * to anyone, then `setTreasuryWallet()` again to itself to steal all
     * the tokens from the intermediate account. By requiring an `approve()`
     * function for `adminWallet` to move tokens that do not belong to it,
     * we solve this exploit and require the `treasuryWallet` to `approve()`
     * the `adminWallet` thereby giving authorizsation to move its tokens.
     * 
     * @notice
     * `treasuryWallet` can replace itself and set a new `treasuryWallet`.
     * `adminWallet` can strip any `treasuryWallet` of its privileges at any time.
     */
    function setTreasuryWallet(
        address newTreasuryWallet,
        bool transferTokens
    ) public _adminOrTreasuryAuth {
        _execAdminTreasuryWalletChange(
            newTreasuryWallet,
            treasuryWallet,
            transferTokens && adminWallet != treasuryWallet,
            [errors[errSetTreasury0], errors[errSetTreasury1]]
        );

        /**
         * @notice
         * Requiring the outgoing `treasuryWallet` to `approve()` the
         * `adminWallet` in the case where the `adminWallet` is not also
         * the `treasuryWallet` ensures that `adminWallet` cannot rugpull
         * (steal tokens) by the exploit explained at this function's header.
         */
        emit TreasuryChange(treasuryWallet, newTreasuryWallet);
        treasuryWallet = newTreasuryWallet;
    }

    /**
     * @dev
     * Allows `adminWallet` or `treasuryWallet` to set a `guardianWallet`
     * to execute basic housekeeping tasks on the former's behalf. No
     * verification of `address(0)` or other null addresses since that would
     * prohibit `adminWallet` and `treasuryWallet` from deleting the
     * `guardianWallet` should it choose to do so.
     */
    function setGuardianWallet(
        address newGuardianWallet
    ) external _adminOrTreasuryAuth {
        guardianWallet = newGuardianWallet;
    }
    
    /**
     * @dev
     * EVM in 2023 doesn't easily permit looping across a wide battery of
     * accounts. Our workaround is to loop over the same elements across
     * multiple blocks. To ensure that millions of gas isn't wasted when
     * looping across multiple blocks, we set the minimum `gasPerLoop` and
     * `breakAtGasThreshold` variables. We do not see any exploit possible
     * here other than annoying users by artificially inflating the amount
     * of gas required to submit a looping transaction. Any unspent gas
     * is refunded on transaction completion regardless of the values of
     * `gasPerLoop` and `breakAtGasThreshold`.
     * 
     * @notice
     * These two variables are changeable to allow the `adminWallet`,
     * `treasuryWallet`, or `guardianWallet` to adjust the required gas
     * parameters in the two cases:
     *   # Blockchain parameters change.
     *   # Looping transactions revert or run out of gas
     *     instead of gracefully returning.
     */
    function setGasPerLoop(
        uint newGasPerLoop,
        uint newBreakAtGasThreshold
    ) external _adminTreasuryOrGuardianAuth {
        /**
         * @dev
         * Ensure the new `gasPerLoop` would still allow at least a few
         * accounts to be looped over in the `rainAll()` function.
         */
        require(
            newGasPerLoop <= block.gaslimit / 20,
            errors[errSetGasPerLoop]
        );
        
        /**
         * @dev
         * Setting the `gasPerLoop` to the same as `breakAtGasThreshold`
         * could result in sufficient gas being given to run another loop
         * but insufficient to closing the transaction after breaking the
         * loop. For sure setting `breakAtGasThreshold` /below/ `gasPerLoop`
         * could easily result in reverting loops and millions of gas lost.
         */
        require(
            newGasPerLoop < newBreakAtGasThreshold,
            errors[errSetGasValues]
        );

        /**
         * @dev
         * Reasonable to allow a minimum of 3/4 the `block.gaslimit`
         * to be used for looping only before breaking and closing.
         */
        require(
            newBreakAtGasThreshold <= block.gaslimit / 4,
            errors[errSetBreakAtGasThres]
        );

        /**
         * @dev
         * Save the values into storage and update the relevant error message.
         */
        gasPerLoop = newGasPerLoop;
        breakAtGasThreshold = newBreakAtGasThreshold;
        _updateErrorMsg_gasPerLoop();
    }
    
    /**
     * @notice
     * Set a minimum balance required to qualify for
     * inclusion in `rain()` and `rainAll()` functions.
     * 
     * @notice
     * Default is 1 whole token required.
     * Accounts with a fraction of a token, as in <= 0.999999, are excluded.
     */
    function setRainMinimumBalance(
        uint newRainMinimumBalance
    ) external _adminOrTreasuryAuth {

        // Enforce a maximum required balance of 4200.69 tokens.
        require(
            newRainMinimumBalance <= __maxRainThreshold,
            errors[errSetRainMinBalance]
        );

        rainMinimumBalance = newRainMinimumBalance;
    }




    // ------------------------------------------------------------------ //
    //  ----------------------  ERC-20 FUNCTIONS  ----------------------  //

    /**
     * @notice Section dedicated to externally-facing ERC-20 functions.
     */

    /**
     * @dev
     * Prevent tokens from being irrevocably lost by requiring users to submit
     * `transferFrom()` transactions to transfer to a smart contract. While this
     * is unexpected ERC-20 functionality, it's also only applied when a
     * non-contract wallet – a person – transfers directly to an address at
     * which a contract exists. The only exclusions are the `guardianWallet`,
     * `treasuryWallet`, and `adminWallet` since our intent is for those
     * addresses to always be able to accept and manage any and all tokens
     * such as them being multi-sig wallet contracts.
     * 
     * @notice
     * Be aware that `transferFrom()` transactions made by an account owner
     * themselves will bypass the `approve()` requirement and execute
     * as if they were a standard `transfer()` transaction. We consider this
     * acceptable functionality since account owners should always be free to
     * do with their tokens what they like without needing to authorizse
     * themselves. Furthermore, forcing users to call a different function will
     * almost assuredly prevent unintended transfers directly to contracts.
     * Most EVM contracts in 2023 cannot react to tokens sent directly via
     * ERC-20's standard `transfer()` method. By being forced to call a
     * separate function, users are made aware of the danger but may
     * still proceed should they desire to transfer directly to a contract.
     * 
     * @notice ERC-20 required function.
     */
    function transfer(address to, uint amount) external returns (bool) {
        /**
         * @dev
         * If sent directly to a smart contract, tell the user to use
         * `transferFrom()`. This check adds ≈ 3000 gas to a `transfer()`
         * transaction, increasing the cost from ≈ 37000 to ≈ 40000 total.
         */
        require(
            _isContract(msg.sender)
            || !_isContract(to)
            || _walletIsGuardianTreasuryOrAdmin(to),
            errors[errTransferContract]
        );

        return _transfer(msg.sender, to, amount);
    }
    
    /**
     * @return balance -> Of the provided `owner`.
     * @notice ERC-20 required function.
     */
    function balanceOf(address owner) external view returns (uint) {
        return balance[owner];
    }

    /**
     * @return allowance -> That the `_account` has granted the `_spender`.
     * @notice ERC-20 required function.
     */
    function allowance(
        address owner,
        address spender
    ) public view returns (
        uint
    ) {
        /**
         * @dev
         * If the `allowanceTimeToLive` set by the `_owner` is
         * 0 then the `allowance` is perpetual. Otherwise,
         * any non-zero number should be treated as the
         * number of seconds into the future the user intends
         * for their `_spender`s `allowance` to expire.
         * 
         * @dev
         * If current time is in the future from the `owner`s
         * `allowanceTimeToLive` number of seconds plus when the
         * `approve()` AKA `allowance` was set, then show that the
         * `allowance` is 0 (expired). Otherwise, return the calculated
         * value based on the actual one stored in the `allowances` mapping.
         */
        return _calcAllowance(owner, spender, allowanceTimeToLive[owner])[aAllowance];
    }

    /**
     * @notice
     * 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.
     * 
     * @notice
     * While the Ethereum community states, "One possible solution to mitigate
     * this race condition is to first reduce the spender's `allowance` to 0
     * and set the desired value afterwards" we do not see how unfortunate
     * transaction ordering can't still spend the outgoing `allowance` before
     * it is set to 0.
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     * https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM
     * 
     * @notice ERC-20 required function.
     */
    function approve(address spender, uint amount) external returns (bool) {
        return _approve(msg.sender, spender, amount);
    }

    /**
     * @notice
     * Defined with `public` visibility to allow for use in `setTreasuryWallet()`.
     * Pre-requisite to use: Owner gives an `allowance` to the `sender`.
     * `sender` may now `transferFrom()` `owner` to any `recipient` of their
     * choosing for any amount up to `allowance[owner][recipient][aAllowance]`.
     * 
     * @notice
     * Since the transfer may be called with the possibility of
     * `from` != `msg.sender` we opt for the variable name
     * `owner` instead of `from`, and `recipient` instead of `to`.
     * 
     * @notice ERC-20 required function.
     */
    function transferFrom(
        address owner,
        address recipient,
        uint amount
    ) public returns (bool) {
        uint _allowance = allowance(owner, msg.sender);

        /**
         * @notice
         * Always allow a transaction where the `msg.sender` is the `owner`
         * by adjusting `allowances`, essentially giving a token holder unlimited
         * `allowance` for themselves to mirror `transfer()` functionality.
         */
        if (msg.sender == owner && _allowance <= amount) {
            /**
             * @dev
             * Costs less gas to check `if{}` statement than to `delete` if
             * already set to 0. Very likely a `msg.sender` won't ever set
             * their allowance at all meaning it'll be 0 most of the time.
             */
            if (_allowance > 0) {
                delete allowances[msg.sender][msg.sender][aAllowance];
            }
        }
        /**
         * @notice
         * Otherwise if the `msg.sender` is not the `owner` or if they provided
         * themselves with sufficient `allowance`, then continue into the
         * `else{}` statement.
         */
        else {
            /**
             * @dev
             * Nesting the `require()` this way ensures lower gas cost since we
             * allow execution if `msg.sender` == `sender` with the special
             * case of a token holder wanting to directly call `transferFrom()`
             * themselves. That special case exists because of our desire to
             * prevent the extremely common user error of using `transfer()`
             * to send directly to a smart contract. These smart contracts
             * in 2023 EVM won't typically register they've received anything
             * and thus the tokens will be lost forever. The common exception
             * is a multi-sig wallet via smart contract which we have no ability
             * to identify and exempt from our checks.
             */
            require(
                _allowance >= amount,
                string.concat(
                    errors[errInsufficientAllowance],
                    _tokenValueAsString(_allowance)
                )
            );

            /**
             * @dev
             * Disallow the subtraction of `allowance` by `amount`
             * if `_allowance != type(uint).max`. Saves ≈ 2k gas
             * in the case of an `owner` setting `spender`s
             * `allowance` to be effectively unlimited. While this
             * doesn't strictly adhere to the ERC-20 standard, this
             * functionality is quite common and saves gas when there
             * exists no materially significant outcome difference.
             */
            if (_allowance != type(uint).max) {
                allowances[owner][msg.sender][aAllowance] -= amount;
            }

            /**
             * @dev
             * Important to note that we use `msg.sender` NOT `recipient` since
             * the former adheres to the ERC-20 standard whereas requiring
             * `msg.sender` == `recipient` or checking the `recipient`s
             * `allowance` is standard-breaking. Many protocols have a
             * higher-level contract administer – commonly known as a router –
             * to `transferFrom()` a user to a separate contract for actual
             * execution. This means the `msg.sender` will be approved but
             * a `recipient` may not be.
             */
        }

        // Execute the transfer and emit a {Transfer} event.
        return _transfer(owner, recipient, amount);
    }




    // ------------------------------------------------------------------ //
    //  ------------------  ERC-20 EXTENDED FUNCTIONS  -----------------  //

    /**
     * @notice Section dedicated to extended EIP-2612 functionality. 
     * 
     * @notice
     * Function name uses "Approvals" instead of "Allowances" because its
     * purpose is to delete all information related a given spender on sender's
     * behalf. If we were only erasing the amount – as in the value stored at
     * the `aAllowance` index in the `allowances` array – then we would've opted
     * for "eraseAllAllowances()" as a function name. Instead this function
     * destroys all traces of all approvals if run with `_onlyExpired` == false.
     * 
     * @notice EIP-2612 extended function.
     */
    function eraseAllApprovals(
        bool onlyExpired
    ) external returns (
        bool
    ) {
        return _eraseAllApprovals(onlyExpired, allowanceTimeToLive[msg.sender]);
    }

    /**
     * @dev
     * Setting an account's `allowanceTimeToLive` to less than
     * ≈ 30 seconds could very easily result in transfers
     * bricking. Can be set to 0 to remove the limit entirely.
     * 
     * @notice ERC-20 extended function.
     */
    function setAllowanceTimeToLive(uint newAllowanceTimeToLive) external {
        require(
            (
                newAllowanceTimeToLive >= __minSecsAllowanceTimeToLive // 30 seconds
                && newAllowanceTimeToLive <= type(uint248).max
            )
            || newAllowanceTimeToLive == 0,
            // Otherwise, give an error.
            errors[errSetAllowanceTimeToLive]
        );

        /**
         * @dev
         * To ensure lingering `approve()`s don't suddenly appear, the best
         * course of action is to `eraseAllApprovals()` if the user is
         * setting their `allowanceTimeToLive` to:
         *   # A different length of time than their current setting
         *   # AND is either setting it to
         *      # 0 (that being perpetual/indefinite `approve()`s)
         *      # A longer duration of time than their current setting
         * In those scenarios we'd want to `eraseAllApprovals()`s.
         * Setting the `allowanceTimeToLive` to a /stricter/ setting such as
         * going from default 0 to 30 or from 60 to 45 seconds would not
         * need to invoke the `eraseAllApprovals()` since that would see
         * current `approve()`s become invalidated rather than previously
         * invalidated `approve()`s suddenly becoming valid again.
         */
        uint248 _allowanceTimeToLive = allowanceTimeToLive[msg.sender];
        if (
            _allowanceTimeToLive != newAllowanceTimeToLive
            && (
                newAllowanceTimeToLive == 0
                || (
                    _allowanceTimeToLive > 0
                    && newAllowanceTimeToLive > _allowanceTimeToLive
                )
            )
        ) {
            /**
             * @dev
             * Stricter (shorter) time limits needn't
             * access and erase storage values since
             * they still get calculated as 0.
             */
            if (!_eraseAllApprovals(true, _allowanceTimeToLive)) {
                return;
            }
        }

        allowanceTimeToLive[msg.sender] = uint248(newAllowanceTimeToLive);
    }

    /**
     * @dev
     * Allow the `msg.sender` to decide if they want to enable perpetual
     * approvals for the given `spender` or to delete/disable such setting.
     */
    function setAllowancePerpetual(address spender, bool enable) external {
        /**
         * @dev
         * Prevent zombie `approve()`s from being revived.
         * No possible gas savings over accessing `aAllowance`
         * directly and then needing to fallback to
         * `_calcAllowance()` in most scenarios anyway.
         */
        if (allowance(msg.sender, spender) == 0) {
            /**
             * @dev
             * Since we already know the allowance is 0 with the
             * current expiration, delete the `aAllowance` amount
             * to prevent it from being potentially revived after we
             * set the account to perpetual – unending – expiration.
             */
            delete allowances[msg.sender][spender][aAllowance];
        }

        /**
         * @dev Enable perpetual approvals by setting to non-zero.
         */
        allowances[msg.sender][spender][aPerpetual] =
            enable ? block.timestamp : 0;
    }

    /**
     * @notice ERC-20 extended function.
     */
    function increaseAllowance(
        address spender,
        uint amountToAdd
    ) external returns (
        bool
    ) {
        uint _allowance = allowance(msg.sender, spender);
        return _approve(msg.sender, spender, _allowance + amountToAdd);
    }

    /**
     * @notice ERC-20 extended function.
     */
    function decreaseAllowance(
        address spender,
        uint amountToDeduct
    ) external returns (
        bool
    ) {
        uint _allowance = allowance(msg.sender, spender);
        require(
            _allowance >= amountToDeduct,
            string.concat(
                errors[errDecreaseAllowance],
                _tokenValueAsString(_allowance)
            )
        );
        return _approve(msg.sender, spender, _allowance - amountToDeduct);
    }

    /**
     * @notice Batch-transfer a list of index-linked recipients and amounts.
     * 
     * @dev
     * Give the list of recipients the amount in the `amounts` list
     * using the index as a link between the two. The lists
     * must be of identical length to avoid unintended transfers.
     * 
     * @notice ERC-20 extended function.
     */
    function transferMultiple(
        address[] calldata recipients,
        uint[] calldata amounts
    ) external {
        require(
            recipients.length == amounts.length,
            errors[errTransferMultiple]
        );
        _transferMultiple(msg.sender, false, recipients, amounts);
    }




    // ------------------------------------------------------------------ //
    //  ---------------------  EIP-2612 FUNCTIONS  ---------------------  //

    /**
     * @notice Section dedicated to all EIP-2612 logic. 
     */

    /**
     * @dev
     * This packed bytes may NOT be altered in any way
     * without completely breaking compatibility with
     * the EIP-2612 standard. EIP-2612 relies on
     * having a `PERMIT_TYPEHASH` that
     * returns an >> identical << result in Web3xx.
     * 
     * @notice EIP-2612 required variable.
     */
    bytes32 private constant PERMIT_TYPEHASH = keccak256(
        "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
    ); // == 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9

    /**
     * @notice Estimated gas cost ≈ 250,000.
     * @notice EIP-2612 required function.
     * 
     * @dev Helpful links related to gasless approvals:
     * https://eips.ethereum.org/EIPS/eip-2612
     * https://soliditydeveloper.com/erc20-permit
     * https://github.com/Uniswap/v3-periphery/blob/main/test/shared/permit.ts
     * https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2ERC20.sol#L81
     * https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol#L112
     * https://github.com/soliditylabs/ERC20-Permit/blob/main/contracts/ERC20Permit.sol#L33
     * https://anettrolikova.medium.com/permits-as-free-approval-messages-for-signing-transactions-6f9b7c1b7ee0
     * https://github.com/ethereum/EIPs/pull/5987#issuecomment-1351327168
     * https://twitter.com/dmihal/status/1251505379391004672
     * https://eips.ethereum.org/EIPS/eip-777
     * https://www.blockchain-council.org/ethereum/ethereum-tokens-erc-20-vs-erc-223-vs-erc-777/
     * 
     * @dev
     * Executing with the `++` as a suffix on `nonces` will grab the current
     * `nonces` value, then increment by 1 after resolution of the `keccak256()`
     * calculation. We could of course write `++nonces[owner]` on a new line
     * after the function execution. However, writing the logic this way makes
     * it clear the nonce is used then incremented after its use.
     */
    function permit(
        address owner,
        address spender,
        uint value,
        uint deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(
            deadline >= block.timestamp,
            errors[errPermitDeadline]
        );

        bytes32 _digest = keccak256(
            abi.encodePacked(
                hex"1901", // == "\x19\x01"
                _getAndSaveDomainSeparator(),
                keccak256(
                    abi.encode(
                        PERMIT_TYPEHASH,
                        owner,
                        spender,
                        value,
                        nonces[owner]++,
                        deadline
                    )
                )
            )
        );

        /**
         * @dev
         * Verify the `owner` matches the signature. VERY important.
         * This entire `permit()` and EIP-2612 gasless approval
         * system hinges on the ability to recover the `owner`
         * from the `v`, `r`, and `s` values given, and then for
         * those values to match the `_digest` calculated based
         * on the other arguments provided.
         */
        require(
            owner == ecrecover(_digest, v, r, s),
            errors[errPermitBadSig]
        );

        /**
         * @dev
         * `require()`s placed in order of
         * most likely to least likely to fail
         * to save gas on invalid executions.
         */
        require(
            owner != address(0),
            errors[errPermit0]
        );

        /**
         * @dev Execute the approval.
         */
        _approve(owner, spender, value);
    }

    /**
     * @dev
     * Ideally we'd create a nested mapping to ensure any particular user
     * can create permits across multiple dApps without a nonce collision
     * occurring. Since there is only a single nonce, then each user could
     * only `permit()` one dApp at a time rather than being able to
     * simultaneously interact with multiple. On the plus side, ensuring a
     * user's `nonce` is the same across their entire account does enable the
     * ability to burn previous `permit()`s more easily and allows dApps
     * to more easily create signatures in Web3xx.
     * 
     * @notice EIP-2612 required variable.
     */
    mapping (address => uint) public nonces;

    /**
     * @notice EIP-2612 extended function.
     * 
     * @notice
     * Allows a user to burn the oldest unused and previously-signed message,
     * thereby burning a previous `permit()` --> `approve()` they created.
     */
    function permitBurn() external {
        ++nonces[msg.sender];
    }

    /**
     * @notice EIP-2612 required variable.
     */
    bytes32 private constant EIP712_DOMAIN = 
        keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );

    /**
     * @notice EIP-2612 required variable.
     */
    bytes32 public DOMAIN_SEPARATOR;

    /**
     * @notice EIP-2612 derivative required variable.
     */
    uint public chainId;

    /**
     * @notice EIP-2612 required function.
     */
    function saveDomainSeparatorAndChainId() public {
        chainId = block.chainid;
        /**
         * @dev
         * From EIP-712.
         * https://eips.ethereum.org/EIPS/eip-712
         * None of these fields can be altered in any way
         * without completely breaking compatibility with
         * the EIP-2612 standard, which itself relies on
         * having a `DOMAIN_SEPARATOR` per EIP-712 that
         * returns an >> identical << result in Web3xx.
         */
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                EIP712_DOMAIN,             // EIP-712 required: Defined
                keccak256(bytes(name)),    // EIP-712 required: Generated
                keccak256(bytes(version)), // EIP-712 required: Defined
                block.chainid,             // EIP-712 required: Generated
                address(this)              // EIP-712 required: Generated
            )
        );
    }

    /**
     * @dev
     * Grabs the `DOMAIN_SEPARATOR` and updates only
     * if the `block.chainid` changes.
     * 
     * @notice
     * MUST be run during `constructor()` AFTER `name` is saved.
     * 
     * @notice EIP-2612 extended function.
     */
    function _getAndSaveDomainSeparator() private returns (bytes32) {
        if (block.chainid != chainId) { saveDomainSeparatorAndChainId(); }
        return DOMAIN_SEPARATOR;
    }
    // --------- EIP-2612 support ending ---------




    // ------------------------------------------------------------------ //
    //  -----------------------------  RAIN  ---------------------------  //

    /**
     * @notice
     * The operation herein is identical to `rainAll()`. The `_amount`
     * applies to each account rained such that the total spend per `rain()`
     * is equal to { `_accountsToRain` x `_amount` }. If someone `rain()`s
     * 10 on 10 accounts, they will have `_transfer()`d away 100 tokens.
     */
    function _rain(
        address _owner,
        uint _amount,
        uint _accountsToRain
    ) private {
        _rainAndListChecks(_owner, _amount, _accountsToRain, true);

        // Attempted randomness.
        uint _firstId =
            uint(
                keccak256(
                    abi.encodePacked(
                        tx.gasprice,
                        block.timestamp,
                        block.number,
                        _amount,
                        _accountsToRain
                    )
                )
            ) % (numAccounts + 1); // Prevent modulo by 0.
        
        uint _increment =
            uint(
                keccak256(
                    abi.encodePacked(
                        blockhash(block.number - 1),
                        block.timestamp % (_firstId + 1),
                        gasleft(),
                        _accountsToRain
                    )
                )
            ) % (_accountsToRain + 1); // Prevent modulo by 0.
        
        uint _randomNumber =
            uint(
                keccak256(
                    abi.encodePacked(
                        blockhash(block.number - 2),
                        _owner,
                        account[numAccounts],
                        gasleft() / 2,
                        _firstId,
                        _increment
                    )
                )
            );

        // Increase randomness.
        if (_randomNumber % 2 == 0) {
            ++_firstId;
        }
        if (_randomNumber % 6 == 0) {
            ++_increment;
        }
        if (_randomNumber % 7 == 0) {
            ++_firstId;
        }
        if (_randomNumber % 13 == 0) {
            ++_increment;
        }
        if (_firstId > numAccounts) {
            _firstId %= numAccounts;
        }
        if (_increment > numAccounts) {
            _increment %= numAccounts;
        }

        // Ensure no 0 values at the start.
        if (_firstId == 0) {
            ++_firstId;
        }
        if (_increment == 0) {
            ++_increment;
        }

        uint _startId = _firstId;
        uint _randomId = _startId;
        uint i;
        uint _excluded;

        for (; i < _accountsToRain; ++i) {
            // Close the `rain()` if gas is running out.
            if (
                _hasInsufficientGasRemaining()
                && i > 0
                && i + 1 < _accountsToRain
            ) {
                break;
            }

            /**
             * @notice
             * If the end of the accounts list has been reached,
             * wrap around and continue.
             */
            if (_randomId > numAccounts) {
                _randomId -= numAccounts;
            }

            /**
             * @notice
             * If the current user to rain has already been rained,
             * since they were the `_startId` and `i` is no longer 0,
             * then seek forward by increments of 1 until the end of the
             * list is reached. If the rain is still ongoing, reset `_startId`
             * to one account before the `_firstId` and traverse backwards to
             * the 0 index. If the rain is /still/ ongoing after the `_startId`
             * hitting every single member in the accounts list, which will
             * occur when `_startId` == 0, then restart from
             * the original `_firstId`.
             */
            if (_randomId == _startId && i > 0) {
                if (_startId >= _firstId) {
                    ++_startId;
                }
                else {
                    --_startId;
                }

                if (_startId == 0) {
                    _startId = _firstId;
                }

                if (_startId > numAccounts) {
                    _startId = _firstId - 1;
                    /**
                     * @dev
                     * `_firstId` will always start at 1 or greater
                     * since above we evaluate `_firstId == 0`
                     * to result in `++_firstId`.
                     */
                }

                _randomId = _startId; /** This `_startId` should
                 * be different from the one compared at the beginning
                 * of this entire `if{}` flow.
                 */
            }

            /**
             * @dev
             * If this loop results in a skip, whether or not the `_randomId`
             * had their `id` set to 0 doesn't matter since we'll increment
             * `_excluded` even for a delete. Furthermore `_randomId` is
             * verified to be not greater than `numAccounts` at the start
             * of each loop. When compared to `i`, `_excluded` will be
             * an accurate number of loops in which no rain took place.
             */
            if (
                !_execRain(
                    _owner,
                    account[_randomId],
                    _amount
                )
            ) {
                /**
                 * @dev
                 * Make sure to continue for one additional loop
                 * if this one was an unsuccessful rain transfer.
                 * This should ensure that at the end of the
                 * function, `i` - `_excluded` == the `_owner`s
                 * originally intended number of accounts to rain.
                 */
                ++_excluded;
                ++_accountsToRain;
            }

            _randomId += _increment;
        }

        /**
         * @param _delegated -> `false` submitted since this function
         * should never run across multiple blocks and therefore
         * we needn't remember any info into `delegationMem`.
         */
        _rainEnd(_owner, false, 0, 0, _amount * (i - _excluded));
    }

    /**
     * @notice Externally facing for anyone to use on their own behalf.
     */
    function rain(uint amount, uint accountsToRain) external {
       _rain(msg.sender, amount, accountsToRain);
    }

    /**
     * @notice Give `_amount` to each `_recipient` in the list.
     */
    function _rainList(
        address _owner,
        bool _delegated,
        uint _amount,
        address[] calldata _recipients
    ) private {
        uint _end = _recipients.length;
        _rainAndListChecks(_owner, _amount, _end, true);

        uint _firstId;
        uint i;

        if (_delegated) {
            i = delegationMem[_owner][startIndex];
            _firstId = i;
        }

        for (; i < _end; ++i) {
            if (
                _delegated
                && _hasInsufficientGasRemaining()
                && i > _firstId
                && i + 1 < _end
            ) {
                break;
            }

            /**
             * @notice
             * No verification of `rainMinimumBalance`
             * nor if the `recipient` is a smart contract
             * where tokens may be irreversibly lost.
             */
            _transfer(_owner, _recipients[i], _amount);
        }

        _rainEnd(_owner, _delegated, 0, i, _amount * (i - _firstId));

        if (i >= _recipients.length) {
            emit RainList(_owner, _amount * _recipients.length);
        }
    }
    
    /**
     * @notice Give `amount` to each `_recipient` in the list.
     */
    function rainList(uint amount, address[] calldata recipients) external {
        _rainList(msg.sender, false, amount, recipients);
    }

    /**
     * @notice
     * This will revert if there are 0 accounts.
     * This will skip raining on the owner's address.
     * Rains `_amount` to every single `account`
     * that qualifies inside `_execRain()`.
     */
    function _rainAll(
        address _owner,
        bool _delegated,
        uint _amount
    ) private {
        _verifyLoopGas(maxRecipientsPerBlock); // Go for calculated max per block.
        uint _firstId =
            _delegated
            ? delegationMem[_owner][startIndex]
            : rainAllNextId[_owner];

        /**
         * @dev
         * Avoid `rainAll()` on address(0).
         * Ensure this check occurs /after/ the `_delegated` if{} statement
         * above which sets `_firstId` to `delegationMem[startIndex]`.
         */
        if (_firstId == 0) {
            ++_firstId;
        }

        // Slightly more gas efficient to create variables outside a `for` loop.
        uint i = _firstId;
        uint _lastIdToRain = i + (balance[_owner] / _safeDivision(_amount));
        uint _excluded;
        address _recipient;

        // Time to loop until we run out of gas or reach `_lastIdToRain`.
        for (; i <= _lastIdToRain;) {
            /**
             * @dev
             * Don't break unless at least one account has been rained on
             * and also don't break if there's only one account remaining.
             */
            if (
                _hasInsufficientGasRemaining()
                && i < numAccounts
                && i > _firstId
                && i < _lastIdToRain
            ) {
                break;
            }

            /**
             * @dev
             * `numAccounts` can be incremented down
             * by `_execRain()`s `_setId()` function.
             * Thus we need a verification on each
             * loop to ensure we don't start looping
             * across null accounts beyond the ones
             * that exist.
             */
            if (_lastIdToRain > numAccounts) {
                /**
                 * @dev
                 * If `i` has become greater than `numAccounts`
                 * then break to avoid an infinite loop
                 * going up through default values of `address(0)`.
                 */
                if (i > numAccounts) {
                    break;
                }

                _lastIdToRain = numAccounts;
            }

            /**
             * @notice Skips if the `_owner` is the token `_recipient`.
             * @dev If `lastIdToRain` becomes larger than `numAccounts`
             * from this interaction, it'll get fixed on the next loop
             * before hitting any user. In case the `_owner` is the last
             * account registered, the loop will break above( inside the
             * `lastIdToRain` > `numAccounts` if{} flow).
             */
            _recipient = account[i];

            if (
                !_execRain(
                    _owner,
                    _recipient,
                    _amount
                )
            ) {
                /**
                 * @dev
                 * If the account was not deleted (in which case `numAccounts`
                 * would be incremented down), then permit an extra loop.
                 */
                if (id[_recipient] > 0) {
                    ++_excluded;
                    ++i;
                    /**
                     * @dev
                     * Since this rain transfer was unsuccessful and the
                     * account was not deleted (meaning it `_isContract()`),
                     * then increment `lastIdToRain` up by 1 on the condition
                     * that it isn't already a value of `numAccounts` or greater.
                     */
                    if (_lastIdToRain < numAccounts) {
                        ++_lastIdToRain;
                    }
                }

                continue;
            }
            ++i;
        }
        
        /**
         * @dev
         * Prevent a revert if we make a simple math error in how many tokens
         * were rained during this `rainAll()` execution.
         */
        uint _rainedAmount;
        if (i > _excluded + _firstId) {
           _rainedAmount = _amount * (i - _excluded - _firstId);
        }

        _rainEnd(
            _owner,
            _delegated,
            0,
            i,
            _rainedAmount
        );
        
        /**
         * @notice
         * Save the progress of the `rainAll()` if the `_owner` == `msg.sender`
         * where the rained tokens came from the account calling this function.
         */
        if (!_delegated) {
            // Nested if{} with additional variable `rainAllNextId` set to `i`.
            if (_rainedAmount > 0) {
                rainAllRunningTotal[_owner] += _rainedAmount;
            }
            rainAllNextId[_owner] = i;
        }

        /**
         * @dev
         * If not every account was rained on, emit a standard {Rain} event
         * then return to prevent further logic execution and to ensure
         * the `rainAllNextId` and `rainAllRunningTotal` are both
         * properly saved for future completion.
         */
        if (i < numAccounts) {
            return;
        }

        /**
         * @dev
         * If `_delegated` == true and completed – as evidenced by
         * `i` >= `numAccounts` – then emit a {RainAll} event and
         * return to avoid overwriting `msg.sender`s self-made progress
         * of `rainAllNextId` and `rainAllRunningTotal`. The
         * `delegationMem` structure should be deleted in the parent
         * `runMyDelegation()` function if this event is hit.
         */
        if (_delegated) {
            emit RainAll(_owner, delegationMem[_owner][total]);
            return;
        }

        /**
         * @dev
         * All logic below here should only run if the `msg.sender`
         * is the account out of which the rain is paid.
         */
        emit RainAll(_owner, rainAllRunningTotal[_owner]);

        // Reset the _owner's next account to rain variable.
        rainAllNextId[_owner] = 1;

        // Erase the running total number of tokens the `_owner` has rained.
        delete rainAllRunningTotal[_owner];
    }

    /**
     * @dev
     * Costs ≈ 40,000 gas per recipient
     * for a soft cap of 198 recipients per block.
     */
    function rainAll(uint amount) external {
        _rainAll(msg.sender, false, amount);
    }

    /**
     * @dev Saves info if `_delegated` and emits a {Rain} event.
     */
    function _rainEnd(
        address _owner,
        bool _delegated,
        uint _excluded,
        uint _i,
        uint _rainedAmount
    ) private returns (
        uint
    ) {
        if (_delegated) {
            if (_rainedAmount > 0) {
                delegationMem[_owner][total] += _rainedAmount;
            }
            if (_excluded > 0) {
                delegationMem[_owner][excluded] += _excluded;
            }
            
            delegationMem[_owner][startIndex] = _i;

            _excluded = delegationMem[_owner][excluded];
        }
        emit Rain(_owner, _rainedAmount);
        return _excluded;
    }




    // ------------------------------------------------------------------ //
    //  -------------------------  DELEGATION  -------------------------  //
    
    /**
     * @notice
     * Our intent behind delegations is to enable users – most especially the
     * `adminWallet`, `treasuryWallet`, and `guardianWallet` – to execute
     * functions via an external, (likely) scripted wallet that may loop
     * across multiple blocks. This allows all the security that comes with
     * `address`-specific authentication with the flexibility and loop-ability
     * of scriptable software wallets.
     */
    
    /**
     * @notice
     * Might be worthwhile for someone submitting a delegation to see the
     * encoded output to compare with what the `owner` actually set.
     * If the outputs don't match, don't bother sending the transaction.
     * Explain to the `owner` that the provided Delegation `input`
     * is invalid and doesn't match what they set.
     */
    function encodeDelegation(
        address owner,
        Delegation calldata input
    ) public pure returns (
        uint,
        bytes32
    ) {
        return (
            uint(
                keccak256(
                    abi.encode(
                        owner,
                        input
                    )
                )
            ),
            keccak256(
                abi.encodePacked(
                    input.functionName
                )
            )
        );
    }

    /*
        uint8 constant lenDelegates = 5;
        uint8 constant dFuncSetId = 0;
        uint8 constant dFuncTransferMultiple = 1;
        uint8 constant dFuncRain = 2;
        uint8 constant dFuncRainList = 3;
        uint8 constant dFuncRainAll = 4;
    */
    bytes32[lenDelegates] delegateFunctions = [
        keccak256(abi.encodePacked("setId()")),
        keccak256(abi.encodePacked("transferMultiple()")),
        keccak256(abi.encodePacked("rain()")),
        keccak256(abi.encodePacked("rainList()")),
        keccak256(abi.encodePacked("rainAll()"))
    ];

    /**
     * @dev Verification of the Delegation struct being valid is performed
     * before saving the struct's info to storage.
     * 
     * @param input.delegate -> submit `address(0)` to delete your delegation
     */
    function setMyDelegation(
        Delegation calldata input
    ) external {
        
        delete delegationMem[msg.sender];

        /**
         * @dev Return if the user only intends to delete their delegation.
         */
        if (input.delegate == address(0)) {
            return;
        }
        
        /*
        mapping(address => uint[4]) public delegationMem;

        uint8 constant lenDelegationMem = 4;
        uint8 constant encodedDelegation = 0;
        uint8 constant startIndex = 1;
        uint8 constant total = 2;
        uint8 constant excluded = 3;
        
        struct Delegation {
            address delegate;
            string functionName;
            address[] recipients;
            uint[] amounts;
        }
        */

        bytes32 _functionNameEncoded;
        (
            delegationMem[msg.sender][encodedDelegation],
            _functionNameEncoded
        ) = encodeDelegation(msg.sender, input);

        /**
         * @dev
         * An alternative way to verify the delegate function is valid
         * written below. Downside of this one is that it doesn't
         * verify that any of the other arguments inside the provided
         * Delegation are valid for the function chosen.
         *
        for (uint8 i; i < lenDelegates; ++i) {
            if (
                _functionNameEncoded
                ==
                delegateFunctions[i]
            ) { return; }
        }
        revert(error_invalidDelegation);
         *
         */

        // Copied requires from `setId()`
        if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncSetId]
        ) {
            require(
                _walletIsGuardianTreasuryOrAdmin(msg.sender),
                errors[errGuardianTreasuryAdminAuth]
            );

            require(
                input.recipients.length
                ==
                input.amounts.length,
                errors[errDelegateSetId]
            );
        }

        // Copied requires from `transferMultiple()`
        else if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncTransferMultiple]
        ) {
            require(
                input.recipients.length
                ==
                input.amounts.length,
                errors[errTransferMultiple]
            );
        }

        // Copied requires from `rainList()`
        else if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncRainList]
        ) {
            require(
                input.amounts.length == 1,
                errors[errRainAmounts]
            );

            _rainAndListChecks(
                msg.sender,
                input.amounts[rAmount],
                input.recipients.length,
                false
            );
        }

        // Copied requires from `rain()`
        else if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncRain]
        ) {

            require(
                input.amounts.length == 2,
                errors[errRainAmounts]
            );

            /**
             * @dev
             * In `rain()`:
             * `amounts[0]` --> `amount`         --> `rAmount`
             * `amounts[1]` --> `accountsToRain` --> `rAccountsToRain`
             */

            _rainAndListChecks(
                msg.sender,
                input.amounts[rAmount],
                input.amounts[rAccountsToRain],
                false
            );
        }
        else {

            // Prevent invalid delegations being set if none of the above hit.
            require(
                _functionNameEncoded
                ==
                delegateFunctions[dFuncRainAll],
                errors[errInvalidDelegation]
            );

            // Copied requires from `rainAll()`
            require(
                input.amounts.length == 1,
                errors[errRainAmounts]
            );
        }
    }
    
    /**
     * @notice Must have the exact parameters set by the `owner`.
     * 
     * @dev
     * Run the delegation entrusted to me.
     * `owner` can run their own delegation even if they chose
     * a different delegate at `input.delegate`.
     */
    function runMyDelegation(
        address owner,
        Delegation calldata input
    ) external {
        require(
            msg.sender != address(0),
            errors[errRunMyDelegation]
        );

        /**
         * @dev
         * Only you or the `delegate` you chose can execute your
         * stored Delegation.
         */
        require(
            msg.sender == input.delegate
            || msg.sender == owner,
            errors[errAuthMyDelegation]
        );

        (
            uint _encodedDelegation,
            bytes32 _functionNameEncoded
        ) = encodeDelegation(owner, input);
        
        /**
         * @dev After encoding the delegation, verify it matches what is stored.
         */
        require(
            _encodedDelegation == delegationMem[owner][encodedDelegation],
            errors[errDelegationDoesntMatch]
        );

        // `setId()` delegation
        if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncSetId]
        ) {
            /**
             * @dev
             * We ran into an issue where neither Remix nor Hardhat
             * would actually push the transaction through the loop
             * with sufficient gas for each account. To get around
             * this limitation of incorrect gas estimation, we simply
             * spoof another few `_accounts` into the gas `require()`
             * to ensure the Tx is pushed with sufficient gas.
             * 
             * @dev
             * Swapping `id`s costs ≈ 50k gas whereas we enforce ≈ 23k per loop.
             * Therefore setting this value to 2x `rain()` ≈ 46k per loop should
             * be sufficient to loop through all the `setId()`s provided.
             * 
             * @dev
             * Should the `gasPerLoop` value increase the worst that happens
             * is users push their Tx with additional gas and are refunded
             * on Tx completion. At least they ensure their gas was
             * spent on actually achieving the action(s) they desired.
             */
            uint _accounts = input.recipients.length;
            
            /**
             * @dev
             * Somewhat more expensive than `rain()` due to our requirement
             * to verify the delegation before running. We estimate that'll
             * cost the same as 2x `rain()` execution loop.
             */
            _verifyLoopGas(_accounts * 2);

            /**
             * @dev
             * Go through the entire list of `_accounts`, starting at
             * the remembered index in the `delegationMem` mapping.
             * By default this index starts at 0.
             */
            uint i = delegationMem[owner][startIndex];
            uint _start = i;
            for (; i < _accounts; ++i) {

                /**
                 * @dev
                 * Insufficient gas remaining?
                 * Remember the current index and return to save progress.
                 */
                if (
                    _hasInsufficientGasRemaining()
                    && i > _start
                    && i + 1 < _accounts
                ) {
                    delegationMem[owner][startIndex] = i;
                    return;
                }
                
                /**
                 * @dev Execute the `setId()` on the given account.
                 */
                _setId(input.recipients[i], input.amounts[i]);
            }
        }

        // `transferMultiple()` delegation
        else if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncTransferMultiple]
        ) {
            /**
             * @dev
             * Looping occurs inside the `_transferMultiple()`
             * private executable.
             */
            _transferMultiple(owner, true, input.recipients, input.amounts);

            if (delegationMem[owner][startIndex] < input.recipients.length) {
                return;
            }
        }

        // `rainList()` delegation
        else if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncRainList]
        ) {
            /**
             * @dev
             * Looping occurs inside the `_rainList()`
             * private executable.
             */
            _rainList(
                owner,
                true,
                input.amounts[rAmount],
                input.recipients
            );

            if (delegationMem[owner][startIndex] < input.recipients.length) {
                return;
            }
        }

        // `rain()` delegation
        else if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncRain]
        ) {

            /**
             * @dev
             * In `_rain()` private executable:
             * `amounts[0]` --> `amount`         --> `rAmount`
             * `amounts[1]` --> `accountsToRain` --> `rAccountsToRain`
             */

            _rain(
                owner,
                input.amounts[rAmount],
                input.amounts[rAccountsToRain]
            );
        }

        // `rainAll()` delegation
        else if (
            _functionNameEncoded
            ==
            delegateFunctions[dFuncRainAll]
        ) {
            /**
             * @dev
             * Looping occurs inside the `_rainAll()`
             * private executable.
             */
            _rainAll(
                owner,
                true,
                input.amounts[rAmount]
            );

            if (delegationMem[owner][startIndex] < numAccounts) {
                return;
            }
        }

        // Invalid or unknown delegation.
        else {
            revert(errors[errInvalidDelegation]);
        }

        /**
         * @dev
         * If delegation is successfully run,
         * delete the delegation to prevent
         * unintended expenditures.
         */
        delete delegationMem[owner];
    }




    // ------------------------------------------------------------------ //
    //  ----------------------  CLAIM LOST ERC-20  ---------------------  //

    /**
     * @notice
     * Our token contract has no way of knowing if it's received tokens.
     * Instead of implementing an ERC-223's `tokenFallback()` functionality
     * or ERC-777's `tokensReceived()` functionality, we opted for a custom
     * and much less complicated approach: Anyone can claim any outside tokens
     * sent to this token contract.
     * 
     * @notice
     * Should tokens be sent to `address(this)` then in `_transfer()`
     * we re-route them to the `treasuryWallet`, thereby ensuring the tokens
     * this contract creates won't ever exist at `address(this)` and thus
     * won't be claimable via the below function.
     */
    function claimERC20(address token) external {
        IERC20 _token = IERC20(token);
        uint tokenBalance = _token.balanceOf(address(this)); // costs 3000 gas
        emit Claimed(token, tokenBalance, msg.sender);

        if (tokenBalance > 0) {
            require(
                _token.transfer(msg.sender, tokenBalance),
                errors[errClaimERC20]
            );
        }
    }




}

// ------------------------------------------------------------------------------------ //



// = = = = = = = = = = = = = = = = = //
//                                   //
//    [email protected]   //
// [email protected] //
//     [email protected]     //
//                                   //
//           20 April 2023           //
// = = = = = = = = = = = = = = = = = //

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_supply","type":"uint256"},{"internalType":"address","name":"_deployer","type":"address"},{"internalType":"address","name":"_guardian","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"AdminChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"origin","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gifter","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountThisBlock","type":"uint256"}],"name":"Rain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"total","type":"uint256"}],"name":"RainAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"total","type":"uint256"}],"name":"RainList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferMultiple","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"TreasuryChange","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"account","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"bool[]","name":"shouldBeProtected","type":"bool[]"}],"name":"addAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"breakAtGasThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"claimERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amountToDeduct","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"denominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"string","name":"functionName","type":"string"},{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct TC.Delegation","name":"input","type":"tuple"}],"name":"encodeDelegation","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bool","name":"onlyExpired","type":"bool"}],"name":"eraseAllApprovals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gasPerLoop","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getAccount","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"bool","name":"protected","type":"bool"},{"components":[{"internalType":"uint248","name":"timeToLive","type":"uint248"},{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"timeRemaining","type":"uint256"},{"internalType":"uint256","name":"perpetualSince","type":"uint256"}],"internalType":"struct TC.Approved[]","name":"list","type":"tuple[]"}],"internalType":"struct TC.Approves","name":"approvedSpenders","type":"tuple"},{"components":[{"internalType":"bool","name":"excluded","type":"bool"},{"internalType":"uint256","name":"allNextId","type":"uint256"},{"internalType":"uint256","name":"allRunningTotal","type":"uint256"},{"internalType":"uint256","name":"delegation","type":"uint256"}],"internalType":"struct TC.RainStruct","name":"rain","type":"tuple"}],"internalType":"struct TC.Account","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getAccountById","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"bool","name":"protected","type":"bool"},{"components":[{"internalType":"uint248","name":"timeToLive","type":"uint248"},{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"timeRemaining","type":"uint256"},{"internalType":"uint256","name":"perpetualSince","type":"uint256"}],"internalType":"struct TC.Approved[]","name":"list","type":"tuple[]"}],"internalType":"struct TC.Approves","name":"approvedSpenders","type":"tuple"},{"components":[{"internalType":"bool","name":"excluded","type":"bool"},{"internalType":"uint256","name":"allNextId","type":"uint256"},{"internalType":"uint256","name":"allRunningTotal","type":"uint256"},{"internalType":"uint256","name":"delegation","type":"uint256"}],"internalType":"struct TC.RainStruct","name":"rain","type":"tuple"}],"internalType":"struct TC.Account","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAccountsList","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"bool","name":"protected","type":"bool"},{"components":[{"internalType":"uint248","name":"timeToLive","type":"uint248"},{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"timeRemaining","type":"uint256"},{"internalType":"uint256","name":"perpetualSince","type":"uint256"}],"internalType":"struct TC.Approved[]","name":"list","type":"tuple[]"}],"internalType":"struct TC.Approves","name":"approvedSpenders","type":"tuple"},{"components":[{"internalType":"bool","name":"excluded","type":"bool"},{"internalType":"uint256","name":"allNextId","type":"uint256"},{"internalType":"uint256","name":"allRunningTotal","type":"uint256"},{"internalType":"uint256","name":"delegation","type":"uint256"}],"internalType":"struct TC.RainStruct","name":"rain","type":"tuple"}],"internalType":"struct TC.Account[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"first","type":"uint256"},{"internalType":"uint256","name":"last","type":"uint256"}],"name":"getAccountsListByIds","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"bool","name":"protected","type":"bool"},{"components":[{"internalType":"uint248","name":"timeToLive","type":"uint248"},{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"timeRemaining","type":"uint256"},{"internalType":"uint256","name":"perpetualSince","type":"uint256"}],"internalType":"struct TC.Approved[]","name":"list","type":"tuple[]"}],"internalType":"struct TC.Approves","name":"approvedSpenders","type":"tuple"},{"components":[{"internalType":"bool","name":"excluded","type":"bool"},{"internalType":"uint256","name":"allNextId","type":"uint256"},{"internalType":"uint256","name":"allRunningTotal","type":"uint256"},{"internalType":"uint256","name":"delegation","type":"uint256"}],"internalType":"struct TC.RainStruct","name":"rain","type":"tuple"}],"internalType":"struct TC.Account[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCirculatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getErrors","outputs":[{"internalType":"string[34]","name":"","type":"string[34]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardianWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amountToAdd","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxRecipientsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numAccounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"permitBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"accountsToRain","type":"uint256"}],"name":"rain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rainAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address[]","name":"recipients","type":"address[]"}],"name":"rainList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rainMinimumBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"string","name":"functionName","type":"string"},{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct TC.Delegation","name":"input","type":"tuple"}],"name":"runMyDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saveDomainSeparatorAndChainId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdminWallet","type":"address"},{"internalType":"bool","name":"transferTokens","type":"bool"}],"name":"setAdminWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"bool","name":"enable","type":"bool"}],"name":"setAllowancePerpetual","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newAllowanceTimeToLive","type":"uint256"}],"name":"setAllowanceTimeToLive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_error","type":"string"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"setError","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newGasPerLoop","type":"uint256"},{"internalType":"uint256","name":"newBreakAtGasThreshold","type":"uint256"}],"name":"setGasPerLoop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGuardianWallet","type":"address"}],"name":"setGuardianWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"setId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"string","name":"functionName","type":"string"},{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct TC.Delegation","name":"input","type":"tuple"}],"name":"setMyDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"bool","name":"shouldBeProtected","type":"bool"}],"name":"setProtected","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRainMinimumBalance","type":"uint256"}],"name":"setRainMinimumBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasuryWallet","type":"address"},{"internalType":"bool","name":"transferTokens","type":"bool"}],"name":"setTreasuryWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"transferMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateErrorMsg_gasPerLoop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"versionNotes","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

60c060405262000014620f42406001620003ac565b600055617aa860015561c3506002556040805160a081018252667365744964282960c81b60c0820152815160a781830301815260c782018352805160209182012082529151717472616e736665724d756c7469706c65282960701b818401529091820190603201604051602081830303815290604052805190602001208152602001604051602001620000b390657261696e282960d01b815260060190565b604051602081830303815290604052805190602001208152602001604051602001620000ef90697261696e4c697374282960b01b8152600a0190565b6040516020818303038152906040528051906020012081526020016040516020016200012a90687261696e416c6c282960b81b815260090190565b60408051601f19818403018152919052805160209091012090526200015490603990600562000352565b503480156200016257600080fd5b5060405162006582380380620065828339810160408190526200018591620004ba565b6003620001938682620005e2565b506004620001a28582620005e2565b506080839052620001b7620f424084620003ac565b60a081905260288054336001600160a01b031991821681179092556029805482169092179091556001600160a01b038481166000818152602e60209081526040808320879055602a80549096169488169490941790945591519384529290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688560a0516040516200027f91815260200190565b60405180910390a2620002916200029c565b50505050506200072c565b466038556040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90620002d390600390620006ae565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f198184030181529190528051602090910120603755565b826005810192821562000383579160200282015b828111156200038357825182559160200191906001019062000366565b506200039192915062000395565b5090565b5b8082111562000391576000815560010162000396565b8082028115828204841417620003d257634e487b7160e01b600052601160045260246000fd5b92915050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200040057600080fd5b81516001600160401b03808211156200041d576200041d620003d8565b604051601f8301601f19908116603f01168101908282118183101715620004485762000448620003d8565b816040528381526020925086838588010111156200046557600080fd5b600091505b838210156200048957858201830151818301840152908201906200046a565b600093810190920192909252949350505050565b80516001600160a01b0381168114620004b557600080fd5b919050565b600080600080600060a08688031215620004d357600080fd5b85516001600160401b0380821115620004eb57600080fd5b620004f989838a01620003ee565b965060208801519150808211156200051057600080fd5b506200051f88828901620003ee565b9450506040860151925062000537606087016200049d565b915062000547608087016200049d565b90509295509295909350565b600181811c908216806200056857607f821691505b6020821081036200058957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005dd57600081815260208120601f850160051c81016020861015620005b85750805b601f850160051c820191505b81811015620005d957828155600101620005c4565b5050505b505050565b81516001600160401b03811115620005fe57620005fe620003d8565b62000616816200060f845462000553565b846200058f565b602080601f8311600181146200064e5760008415620006355750858301515b600019600386901b1c1916600185901b178555620005d9565b600085815260208120601f198616915b828110156200067f578886015182559484019460019091019084016200065e565b50858210156200069e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000808354620006be8162000553565b60018281168015620006d95760018114620006ef5762000720565b60ff198416875282151583028701945062000720565b8760005260208060002060005b85811015620007175781548a820152908401908201620006fc565b50505082870194505b50929695505050505050565b60805160a051615e2962000759600039600081816104560152610f62015260006103b60152615e296000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c8063870a633d116101de578063ad469eb61161010f578063d505accf116100ad578063f02e4b041161007c578063f02e4b0414610898578063f506d635146108a0578063fbcbc0f1146108b3578063fe924c1e146108c657600080fd5b8063d505accf14610823578063dd62ed3e14610836578063e307e1bb14610849578063e520b83f1461085c57600080fd5b8063c4bdb06d116100e9578063c4bdb06d146107d5578063c8427b43146107dd578063d11d8779146107fd578063d2df3e0f1461081057600080fd5b8063ad469eb6146107a6578063b43f06ad146107b9578063c18a7485146107cc57600080fd5b806395d89b411161017c5780639f89090a116101565780639f89090a1461075a578063a05fccef1461076d578063a457c2d714610780578063a9059cbb1461079357600080fd5b806395d89b411461073f57806396ce0795146107475780639a8a05921461075157600080fd5b80638b49f6ee116101b85780638b49f6ee146106f05780638ce25a931461070357806391d6b5851461070c578063957e3fae1461071f57600080fd5b8063870a633d146106955780638955defb146106bd5780638a7f997c146106dd57600080fd5b8063313ce567116102c35780634626402b1161026157806370a082311161023057806370a0823114610623578063719e24c0146106595780637a0ea3fe1461066c5780637ecebe001461067557600080fd5b80634626402b146105a15780634f9fc267146105c157806350261a95146105d457806354fd4d50146105e757600080fd5b806336b19cd71161029d57806336b19cd7146105485780633950935114610568578063426ef74e1461057b5780634540709d1461058e57600080fd5b8063313ce5671461051257806333fd1fe21461052c5780633644e5151461053f57600080fd5b806318160ddd1161033057806323b872dd1161030a57806323b872dd1461049457806324ccc1ba146104a75780632b112e49146104af5780632dd7c658146104b757600080fd5b806318160ddd146104515780631c519ba61461047857806321b2d6c81461048157600080fd5b806306fdde031161036c57806306fdde0314610406578063095ea7b31461041b5780630ea4a9d21461043e57806314de9baa1461044857600080fd5b80630146844f14610393578063047fc9aa146103b157806305aca141146103e6575b600080fd5b61039b6108d9565b6040516103a89190614c03565b60405180910390f35b6103d87f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016103a8565b6103f96103f4366004614c6f565b6109a1565b6040516103a89190614db0565b61040e6109dd565b6040516103a89190614dc3565b61042e610429366004614dfa565b610a6b565b60405190151581526020016103a8565b610446610a7f565b005b6103d860025481565b6103d87f000000000000000000000000000000000000000000000000000000000000000081565b6103d860275481565b61044661048f366004614e32565b610b6d565b61042e6104a2366004614e69565b610dc9565b610446610f0f565b6103d8610f32565b6104ed6104c5366004614c6f565b602d6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103a8565b61051a600681565b60405160ff90911681526020016103a8565b61044661053a366004614c6f565b610fe8565b6103d860375481565b6028546104ed9073ffffffffffffffffffffffffffffffffffffffff1681565b61042e610576366004614dfa565b611073565b61042e610589366004614ea5565b61109e565b61044661059c366004614eda565b6110da565b6029546104ed9073ffffffffffffffffffffffffffffffffffffffff1681565b6104466105cf366004614e32565b611552565b6104466105e2366004614f28565b6115db565b61040e6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b6103d8610631366004614fa0565b73ffffffffffffffffffffffffffffffffffffffff166000908152602e602052604090205490565b610446610667366004614e32565b611651565b6103d860005481565b6103d8610683366004614fa0565b60366020526000908152604090205481565b6106a86106a3366004614eda565b611831565b604080519283526020830191909152016103a8565b6103d86106cb366004614fa0565b602c6020526000908152604090205481565b6104466106eb366004614e32565b6118bd565b6104466106fe366004615000565b611957565b6103d8602b5481565b61044661071a36600461506c565b611ae6565b602a546104ed9073ffffffffffffffffffffffffffffffffffffffff1681565b61040e611e0e565b6103d8620f424081565b6103d860385481565b610446610768366004614fa0565b611e1b565b61044661077b366004615000565b611ea6565b61042e61078e366004614dfa565b611ef2565b61042e6107a1366004614dfa565b611f78565b6104466107b4366004614c6f565b611fe9565b6104466107c7366004614dfa565b611ff8565b6103d860015481565b6104466120b7565b6107f06107eb3660046150a1565b6120c1565b6040516103a891906150c3565b61044661080b3660046150a1565b612128565b61044661081e366004614fa0565b61224d565b610446610831366004615143565b612420565b6103d86108443660046151b6565b6126d0565b610446610857366004614c6f565b61272c565b61040e6040518060400160405280601281526020017f323032332d30342d3230207c2046696e616c000000000000000000000000000081525081565b6107f06128ad565b6104466108ae3660046151e9565b6128c1565b6103f96108c1366004614fa0565b6128cf565b6104466108d43660046150a1565b612997565b6108e1614aac565b604080516104408101909152600560226000835b8282101561099857838201805461090b90615235565b80601f016020809104026020016040519081016040528092919081815260200182805461093790615235565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b5050505050815260200190600101906108f5565b50505050905090565b6109a9614ad4565b6000828152602d60205260409020546109d79073ffffffffffffffffffffffffffffffffffffffff166128cf565b92915050565b600380546109ea90615235565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1690615235565b8015610a635780601f10610a3857610100808354040283529160200191610a63565b820191906000526020600020905b815481529060010190602001808311610a4657829003601f168201915b505050505081565b6000610a783384846129a2565b9392505050565b466038556040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90610ab490600390615313565b604080519182900382208282018252600183527f31000000000000000000000000000000000000000000000000000000000000006020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120603755565b610b7633612abf565b600790610bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b60405180910390fd5b50602954610d3a90839073ffffffffffffffffffffffffffffffffffffffff16838015610c04575060295460285473ffffffffffffffffffffffffffffffffffffffff908116911614155b60408051808201909152806005600e018054610c1f90615235565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4b90615235565b8015610c985780601f10610c6d57610100808354040283529160200191610c98565b820191906000526020600020905b815481529060010190602001808311610c7b57829003601f168201915b50505091835250506020016005600f5b018054610cb490615235565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce090615235565b8015610d2d5780601f10610d0257610100808354040283529160200191610d2d565b820191906000526020600020905b815481529060010190602001808311610d1057829003601f168201915b5050505050815250612b0f565b60295460405173ffffffffffffffffffffffffffffffffffffffff8085169216907f803605f0e28534cba577fd3b24b497857b9d8fd1b4105ce6b37c5c33b83ef76b90600090a350602980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600080610dd685336126d0565b90503373ffffffffffffffffffffffffffffffffffffffff8616148015610dfd5750828111155b15610e26578015610e21573360009081526034602090815260408083209091528120555b610efb565b82811015600b610e3583612c29565b604051602001610e469291906153f7565b60405160208183030381529060405290610e8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb09190614dc3565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610efb5773ffffffffffffffffffffffffffffffffffffffff8516600090815260346020908152604080832033845290915281208054859290610ef590849061544b565b90915550505b610f06858585612c5d565b95945050505050565b3360009081526036602052604081208054909190610f2c9061545e565b90915550565b60285473ffffffffffffffffffffffffffffffffffffffff166000908152602e60205260408120548190610f86907f000000000000000000000000000000000000000000000000000000000000000061544b565b60295460285491925073ffffffffffffffffffffffffffffffffffffffff918216911614610fe35760295473ffffffffffffffffffffffffffffffffffffffff166000908152602e6020526040902054610fe0908261544b565b90505b919050565b610ff133612abf565b60079061102b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50601863fa61715082111561106d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50600055565b60008061108033856126d0565b905061109633856110918685615496565b6129a2565b949350505050565b336000908152603260205260408120546109d79083907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612dd7565b602033611114576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506111226020820182614fa0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061117057503373ffffffffffffffffffffffffffffffffffffffff8316145b6021906111aa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506000806111b88484611831565b73ffffffffffffffffffffffffffffffffffffffff86166000908152603560205260409020549193509150602290831461121f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50603954810361135957600061123860408501856154a9565b915061124f905061124a826002615511565b612eda565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260356020526040902060010154805b828210156113515761128a612fa5565b801561129557508082115b80156112aa5750826112a8836001615496565b105b156112e35773ffffffffffffffffffffffffffffffffffffffff8716600090815260356020526040902082906001015550505050505050565b6113416112f360408801886154a9565b848181106113035761130361531f565b90506020020160208101906113189190614fa0565b61132560608901896154a9565b858181106113355761133561531f565b90506020020135612fb1565b61134a8261545e565b915061127a565b505050611511565b603a5481036113d25761138784600161137560408701876154a9565b61138260608901896154a9565b613052565b61139460408401846154a9565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260356020526040902090915060015b015410156113cd5750505050565b611511565b603c548103611419576113878460016113ee60608701876154a9565b6000816113fd576113fd61531f565b9050602002013586806040019061141491906154a9565b613251565b603b548103611476576113cd8461143360608601866154a9565b6000816114425761144261531f565b9050602002013585806060019061145991906154a9565b600181811061146a5761146a61531f565b9050602002013561339a565b603d5481036114dc576114ad84600161149260608701876154a9565b6000816114a1576114a161531f565b9050602002013561376e565b602b5473ffffffffffffffffffffffffffffffffffffffff8516600090815260356020526040902060016113bf565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152610bb09060239060040161534e565b73ffffffffffffffffffffffffffffffffffffffff841660009081526035602052604081208181556001810182905560028101829055600301555b50505050565b61155c33836126d0565b6000036115955733600090815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120555b806115a15760006115a3565b425b33600090815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091529020600201555050565b6115e433613af5565b60089061161e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506022811061162f5761162f615528565b8282600583602281106116445761164461531f565b019161154c9190836155cc565b60285473ffffffffffffffffffffffffffffffffffffffff1633146006906116a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506028546040805180820190915261177391849173ffffffffffffffffffffffffffffffffffffffff909116908490806005600c0180546116e690615235565b80601f016020809104026020016040519081016040528092919081815260200182805461171290615235565b801561175f5780601f106117345761010080835404028352916020019161175f565b820191906000526020600020905b81548152906001019060200180831161174257829003601f168201915b50505091835250506020016005600d610ca8565b60295460285473ffffffffffffffffffffffffffffffffffffffff9182169116036117a2576117a28282610b6d565b60285460405173ffffffffffffffffffffffffffffffffffffffff8085169216907f38b1065e0d088f6eda3cb9f0efc7bbb9b145907ab0deb0dbfb700d2bb21599e990600090a350602880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000808383604051602001611847929190615836565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020918201209061188a9085018561595a565b60405160200161189b9291906159bf565b60405160208183030381529060405280519060200120915091505b9250929050565b6118c633613af5565b600890611900576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b5073ffffffffffffffffffffffffffffffffffffffff919091166000908152602f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b61196033613af5565b60089061199a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50828181146119ab576119ab615528565b6119b961124a6002836159fe565b60005b81811015611ade576119cc612fa5565b80156119d85750600081115b80156119ed5750816119eb826001615496565b105b156119f957505061154c565b611a28868683818110611a0e57611a0e61531f565b9050602002016020810190611a239190614fa0565b613b2b565b50838382818110611a3b57611a3b61531f565b9050602002016020810190611a509190614ea5565b602f6000888885818110611a6657611a6661531f565b9050602002016020810190611a7b9190614fa0565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611ad78161545e565b90506119bc565b505050505050565b3360009081526035602052604081208181556001810182905560028101829055600301556000611b196020830183614fa0565b73ffffffffffffffffffffffffffffffffffffffff1603611b375750565b6000611b433383611831565b336000908152603560205260409020919091556039549091508103611c0b57611b6b33613af5565b600890611ba5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50611bb360608301836154a9565b9050611bc260408401846154a9565b919091149050600560095b0190611c06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b505050565b603a548103611c3f57611c2160608301836154a9565b9050611c3060408401846154a9565b91909114905060056007611bcd565b603c548103611cd857611c5560608301836154a9565b601e9150600114611c93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50611cd433611ca560608501856154a9565b600081611cb457611cb461531f565b90506020020135848060400190611ccb91906154a9565b90506000613be6565b5050565b603b548103611d8357611cee60608301836154a9565b601e9150600214611d2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50611cd433611d3e60608501856154a9565b600081611d4d57611d4d61531f565b90506020020135848060600190611d6491906154a9565b6001818110611d7557611d7561531f565b905060200201356000613be6565b603d546023908214611dc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50611dd060608301836154a9565b601e9150600114611c06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b600480546109ea90615235565b611e2433612abf565b600790611e5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50602a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600c818414611ee2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b5061154c33600086868686613052565b600080611eff33856126d0565b9050828110156025611f1083612c29565b604051602001611f219291906153f7565b60405160208183030381529060405290611f68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb09190614dc3565b506110963385611091868561544b565b6000611f8333613cd6565b80611f945750611f9283613cd6565b155b80611fa35750611fa383613af5565b600a90611fdd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50610a78338484612c5d565b611ff53360008361376e565b50565b61200133613af5565b60089061203b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506000818152602d602090815260408083205473ffffffffffffffffffffffffffffffffffffffff168352602f90915290205460109060ff16156120ac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50611cd48282612fb1565b6120bf613d0f565b565b6060600d82841115612100576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50602b5482111561211e57602b5491508183111561211e57602b5492505b610a788383613da3565b61213133613af5565b60089061216b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506121776014456159fe565b6015908311156121b4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b5060168183106121f1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506121fd6004456159fe565b60179082111561223a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b5060018290556002819055611cd4613d0f565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152819060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa1580156122bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e09190615a12565b90503373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f7e6632ca16a0ac6cf28448500b1a17d96c8b8163ad4c4a9b44ef5386cc02779e8360405161234191815260200190565b60405180910390a38015611c06576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff83169063a9059cbb906044016020604051808303816000875af11580156123c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e69190615a2b565b60249061154c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b601a4285101561245d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506000612468613e89565b73ffffffffffffffffffffffffffffffffffffffff8916600090815260366020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928c928c928c929091906124c38361545e565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810187905260e001604051602081830303815290604052805190602001206040516020016125649291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000845290830180835281905260ff8716918301919091526060820185905260808201849052915060019060a0016020604051602081039080840390855afa1580156125ea573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151601b915073ffffffffffffffffffffffffffffffffffffffff8a8116911614612668576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50601973ffffffffffffffffffffffffffffffffffffffff89166126b9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b506126c58888886129a2565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526032602052604081205461272490849084907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613ea3565b519392505050565b601e811015801561275c57507effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111155b80612765575080155b60269061279f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50336000908152603260205260409020547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16818114801590612835575081158061283557506000817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff161180156128355750807effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1682115b1561284d57612845600182612dd7565b61284d575050565b5033600090815260326020526040902080547fff00000000000000000000000000000000000000000000000000000000000000167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60606128bc6001602b54613da3565b905090565b611c06336000858585613251565b6128d7614ad4565b73ffffffffffffffffffffffffffffffffffffffff8216600081815260326020908152604080832054815160c081018352602c8452828520548152808401869052858552602e84528285205481840152948452602f8352928190205460ff161515606085015280518082019091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921680835292916080830191810161297e8786613fd8565b9052815260200161298e856141b8565b90529392505050565b611cd433838361339a565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526034602090815260408083209386168352929052908120828155600101548103612a475773ffffffffffffffffffffffffffffffffffffffff84811660009081526033602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169185169190911790555b73ffffffffffffffffffffffffffffffffffffffff8481166000818152603460209081526040808320948816808452948252918290204260019091015590518581527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a35060019392505050565b6000612ae68260295473ffffffffffffffffffffffffffffffffffffffff91821691161490565b806109d7575060285473ffffffffffffffffffffffffffffffffffffffff8381169116146109d7565b6000612b1a85613b2b565b82519110612b55576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb09190614dc3565b50602081015173ffffffffffffffffffffffffffffffffffffffff84811690861603612bae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb09190614dc3565b508115612bea5773ffffffffffffffffffffffffffffffffffffffff83166000908152602e6020526040902054612be89084908690610dc9565b505b73ffffffffffffffffffffffffffffffffffffffff83166000908152603560205260408120818155600181018290556002810182905560030155611511565b6060612c3482614251565b604051612c479190600590602001615a48565b6040516020818303038152906040529050919050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602e6020526040812054821115612c8f856143c3565b90612cc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb09190614dc3565b50612cd183613b2b565b1580612ce15750612ce184614409565b15612d025760295473ffffffffffffffffffffffffffffffffffffffff1692505b73ffffffffffffffffffffffffffffffffffffffff84166000908152602e602052604081208054849290612d3790849061544b565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152602e602052604081208054849290612d71908490615496565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612aad91815260200190565b33600090815260336020908152604080832080548251818502810185019093528083528493830182828015612e4257602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612e17575b50505050509050612e66600282516003612e5c9190615511565b61124a91906159fe565b60005b8151811015612eb157612e96828281518110612e8757612e8761531f565b6020026020010151868661446a565b612ea15750506109d7565b612eaa8161545e565b9050612e69565b506001915083612ed357336000908152603360205260408120612ed391614b44565b5092915050565b6000612ee58261545e565b915081600154612ef59190615511565b600254612f029190615496565b90506064612f1145605a615511565b612f1b91906159fe565b811115612f3c576064612f2f45605a615511565b612f3991906159fe565b90505b805a11601c612f4a83614549565b604051612f5e929190601d90602001615a66565b60405160208183030381529060405290611c06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb09190614dc3565b60005a60025411905090565b6000612fbc83613b2b565b11801561300d575073ffffffffffffffffffffffffffffffffffffffff82166000908152602e6020526040902054158015612ff5575080155b8061300d575060008111801561300d5750602b548111155b600f90613047576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50611cd48282614679565b8261305c81612eda565b6000861561308f575073ffffffffffffffffffffffffffffffffffffffff87166000908152603560205260409020600101545b8060005b8383101561314f578880156130ab57506130ab612fa5565b80156130b657508183115b80156130cb5750836130c9846001615496565b105b61314f576131188a8989868181106130e5576130e561531f565b90506020020160208101906130fa9190614fa0565b88888781811061310c5761310c61531f565b90506020020135612c5d565b5085858481811061312b5761312b61531f565b905060200201358161313d9190615496565b90506131488361545e565b9250613093565b88156131bf5773ffffffffffffffffffffffffffffffffffffffff8a1660009081526035602052604090208190600201600082825461318e9190615496565b909155505073ffffffffffffffffffffffffffffffffffffffff8a1660009081526035602052604090208390600101555b868310613245578973ffffffffffffffffffffffffffffffffffffffff167fc9a1d560030214e7b5a46c36acf49151dc9dd436da71f508b44ca9f9dae6198a8a6132095782613233565b73ffffffffffffffffffffffffffffffffffffffff8c166000908152603560205260409020600201545b60405190815260200160405180910390a25b50505050505050505050565b8061325f8685836001613be6565b600080861561329557505073ffffffffffffffffffffffffffffffffffffffff8616600090815260356020526040902060010154805b82811015613313578680156132ad57506132ad612fa5565b80156132b857508181115b80156132cd5750826132cb826001615496565b105b61331357613302888686848181106132e7576132e761531f565b90506020020160208101906132fc9190614fa0565b88612c5d565b5061330c8161545e565b9050613295565b6133348888600084613325878261544b565b61332f908c615511565b614888565b508381106133905773ffffffffffffffffffffffffffffffffffffffff88167f53df978d4ae97f179e7d856b810e8cd7bd5bfd929a20e9e0051eecd88205347261337e8689615511565b60405190815260200160405180910390a25b5050505050505050565b6133a78383836001613be6565b6000602b5460016133b89190615496565b604080513a602082015242918101919091524360608201526080810185905260a0810184905260c0016040516020818303038152906040528051906020012060001c6134049190615a8e565b90506000613413836001615496565b61341e60014361544b565b4061342a846001615496565b6134349042615a8e565b5a60408051602081019490945283019190915260608201526080810185905260a0016040516020818303038152906040528051906020012060001c6134799190615a8e565b9050600061348860024361544b565b602b546000908152602d6020526040902054904090879073ffffffffffffffffffffffffffffffffffffffff1660025a6134c291906159fe565b6040805160208101959095527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606094851b8116918601919091529190921b16605483015260688201526088810184905260a8810183905260c801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209050613560600282615a8e565b600003613573576135708361545e565b92505b61357e600682615a8e565b6000036135915761358e8261545e565b91505b61359c600782615a8e565b6000036135af576135ac8361545e565b92505b6135ba600d82615a8e565b6000036135cd576135ca8261545e565b91505b602b548311156135e757602b546135e49084615a8e565b92505b602b5482111561360157602b546135fe9083615a8e565b91505b82600003613615576136128361545e565b92505b81600003613629576136268261545e565b91505b82806000805b878210156137455761363f612fa5565b801561364b5750600082115b801561366057508761365e836001615496565b105b61374557602b5483111561367e57602b5461367b908461544b565b92505b838314801561368d5750600082115b156136dd578684106136a9576136a28461545e565b93506136b5565b6136b284615aa2565b93505b836000036136c1578693505b602b548411156136d9576136d660018861544b565b93505b8392505b6000838152602d602052604090205461370e908b9073ffffffffffffffffffffffffffffffffffffffff168b6149a7565b6137295761371b8161545e565b90506137268861545e565b97505b6137338684615496565b925061373e8261545e565b915061362f565b6137618a60008080613757868861544b565b61332f908f615511565b5050505050505050505050565b613779602754612eda565b6000826137ab5773ffffffffffffffffffffffffffffffffffffffff84166000908152603060205260409020546137d5565b73ffffffffffffffffffffffffffffffffffffffff84166000908152603560205260409020600101545b9050806000036137eb576137e88161545e565b90505b8060006137f784614a96565b73ffffffffffffffffffffffffffffffffffffffff87166000908152602e602052604090205461382791906159fe565b6138319083615496565b90506000805b82841161392757613846612fa5565b80156138535750602b5484105b801561385e57508484115b801561386957508284105b61392757602b5483111561388657602b54841161392757602b5492505b506000838152602d602052604090205473ffffffffffffffffffffffffffffffffffffffff166138b78882886149a7565b6139175773ffffffffffffffffffffffffffffffffffffffff81166000908152602c602052604090205415613912576138ef8261545e565b91506138fa8461545e565b9350602b548310156139125761390f8361545e565b92505b613837565b6139208461545e565b9350613837565b60006139338684615496565b85111561395c5785613945848761544b565b61394f919061544b565b6139599088615511565b90505b61396a898960008885614888565b50876139da5780156139b15773ffffffffffffffffffffffffffffffffffffffff8916600090815260316020526040812080548392906139ab908490615496565b90915550505b73ffffffffffffffffffffffffffffffffffffffff891660009081526030602052604090208590555b602b548510156139ef57505050505050505050565b8715613a5c5773ffffffffffffffffffffffffffffffffffffffff891660008181526035602052604090207f62427b06ab2f53f0724decf97d0b787b5884c87d7d7ab86d5e2927b0044e7d7a906002015460405190815260200160405180910390a2505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff89166000818152603160209081526040918290205491519182527f62427b06ab2f53f0724decf97d0b787b5884c87d7d7ab86d5e2927b0044e7d7a910160405180910390a250505073ffffffffffffffffffffffffffffffffffffffff90951660009081526030602090815260408083206001905560319091528120555050505050565b6000613b1c82602a5473ffffffffffffffffffffffffffffffffffffffff91821691161490565b806109d757506109d782612abf565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602c602052604090205480151580613b635750613b6382614409565b15613b6d57919050565b602b60008154613b7c9061545e565b91829055506000818152602d60209081526040808320805473ffffffffffffffffffffffffffffffffffffffff9097167fffffffffffffffffffffffff000000000000000000000000000000000000000090971687179055948252602c9052929092208290555090565b613bf08284615511565b73ffffffffffffffffffffffffffffffffffffffff85166000908152602e60205260409020541015613c21856143c3565b613c33613c2e8587615511565b612c29565b604051602001613c44929190615ad7565b60405160208183030381529060405290613c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb09190614dc3565b50601f82613cc6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb0919061534e565b50801561154c5761154c82612eda565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611096575050151592915050565b613d1a600154614a96565b600254613d27904561544b565b613d3191906159fe565b602755600154613d4090614549565b613d4b600254614549565b613d56602754614549565b604051602001613d6893929190615b2f565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601d90611ff59082615c19565b606082613db1836001615496565b613dbb919061544b565b67ffffffffffffffff811115613dd357613dd3615557565b604051908082528060200260200182016040528015613e0c57816020015b613df9614ad4565b815260200190600190039081613df15790505b5090506000835b838111613e81576000818152602d6020526040902054613e489073ffffffffffffffffffffffffffffffffffffffff166128cf565b8383613e538161545e565b945081518110613e6557613e6561531f565b602002602001018190525080613e7a9061545e565b9050613e13565b505092915050565b60006038544614613e9c57613e9c610a7f565b5060375490565b613eab614b62565b60005b600360ff82161015613f2c5773ffffffffffffffffffffffffffffffffffffffff808616600090815260346020908152604080832093881683529290522060ff821660038110613f0057613f0061531f565b0154828260ff1660048110613f1757613f1761531f565b6020020152613f2581615d33565b9050613eae565b506020810151600090613f40846001615d52565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613f6b9190615496565b905042811115613f8557613f7f428261544b565b60608301525b6000837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16118015613fb857506040820151155b8015613fc657506060820151155b15613fd057600082525b509392505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260336020908152604080832080548251818502810185019093528083526060949383018282801561405b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311614030575b50508351939450839250505067ffffffffffffffff81111561407f5761407f615557565b6040519080825280602002602001820160405280156140f857816020015b6140e56040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b81526020019060019003908161409d5790505b50925060005b818110156141af57600083828151811061411a5761411a61531f565b602002602001015190506000614131888389613ea3565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff85168152825160208083019190915283015181830152606080840151908201529082015160808201528751919250908790859081106141915761419161531f565b60200260200101819052505050806141a89061545e565b90506140fe565b50505092915050565b6141e560405180608001604052806000151581526020016000815260200160008152602001600081525090565b60405180608001604052806141f984613cd6565b1515815273ffffffffffffffffffffffffffffffffffffffff93909316600081815260306020908152604080832054828801528383526031825280832054818801529282526035905220546060909301929092525090565b60608160000361429457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b620f4240820660006142a582614549565b9050811561434d575b6142bc600a620f42406159fe565b82101561434d576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152508160405160200161430b929190615d8a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050614346600a83615511565b91506142ae565b61436261435d620f4240866159fe565b614549565b6040518060400160405280600181526020017f2e00000000000000000000000000000000000000000000000000000000000000815250826040516020016143ab93929190615db0565b60405160208183030381529060405292505050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602e60205260409020546060906009906143f890612c29565b604051602001612c479291906153f7565b600073ffffffffffffffffffffffffffffffffffffffff82161580614445575073ffffffffffffffffffffffffffffffffffffffff821661dead145b806109d7575073ffffffffffffffffffffffffffffffffffffffff8216301492915050565b6000614474612fa5565b610a785750600182156145065733600090815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816845290915281206002015411806144cc575060006144c9338685613ea3565b51115b610a785733600090815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff88168452909152812055610a78565b33600090815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816845290915281208181556001810182905560020155610a78565b60608160000361458c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156145b35761459f8161545e565b90506145ac600a836159fe565b9150614590565b60008167ffffffffffffffff8111156145ce576145ce615557565b6040519080825280601f01601f1916602001820160405280156145f8576020820181803683370190505b5090505b84156110965761460d600a86615a8e565b614618906030615496565b60f81b8161462584615aa2565b935083815181106146385761463861531f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350614672600a866159fe565b94506145fc565b6000818152602d602090815260408083205473ffffffffffffffffffffffffffffffffffffffff168352602f90915290205460ff16156146b7575050565b806000036147fb5773ffffffffffffffffffffffffffffffffffffffff82166000908152602f602052604090205460ff16156146f1575050565b602b805473ffffffffffffffffffffffffffffffffffffffff8481166000908152602c602081815260408084208054808652602d808552838720805499885284882080548a16808a52979096529387208054929055915581547fffffffffffffffffffffffff00000000000000000000000000000000000000009081169094179091558154959094169490911693909317909255825490928261479383615aa2565b9091555081526020808201929092526040908101600090812080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905573ffffffffffffffffffffffffffffffffffffffff949094168452602c90915282209190915550565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152602c602081815260408084208054808652602d8452828620805497875283872080548a16808952969095529290952080549590559390935582547fffffffffffffffffffffffff000000000000000000000000000000000000000090811690921790925581541691909216179055565b6000841561494d5781156148d55773ffffffffffffffffffffffffffffffffffffffff86166000908152603560205260409020829060020160008282546148cf9190615496565b90915550505b831561491a5773ffffffffffffffffffffffffffffffffffffffff86166000908152603560205260409020849060030160008282546149149190615496565b90915550505b73ffffffffffffffffffffffffffffffffffffffff86166000908152603560205260409020600181018490556003015493505b8573ffffffffffffffffffffffffffffffffffffffff167fb45345ab7bd05accbf85ceae28de4abb6b29a27e3e56ba477bd8946e5da6ee1a8360405161499591815260200190565b60405180910390a25091949350505050565b60008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480614a08575073ffffffffffffffffffffffffffffffffffffffff83166000908152602f602052604090205460ff165b80614a175750614a1783614409565b610a785773ffffffffffffffffffffffffffffffffffffffff83166000908152602e602052604090205480158015614a50575060008054115b15614a6657614a60846000614679565b50610a78565b614a6f84613cd6565b15614a7a5750610a78565b6000548110613fd057614a8e858585612c5d565b915050610a78565b600081600003614aa857506001919050565b5090565b6040518061044001604052806022905b6060815260200190600190039081614abc5790505090565b6040805160c08101825260008082526020808301829052828401829052606080840183905284518086019095529184528301529060808201908152602001614b3f60405180608001604052806000151581526020016000815260200160008152602001600081525090565b905290565b5080546000825590600052602060002090810190611ff59190614b80565b60405180608001604052806004906020820280368337509192915050565b5b80821115614aa85760008155600101614b81565b60005b83811015614bb0578181015183820152602001614b98565b50506000910152565b60008151808452614bd1816020860160208601614b95565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020808252600090610460830183820185845b6022811015614c63577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0878503018352614c51848351614bb9565b93509184019190840190600101614c16565b50919695505050505050565b600060208284031215614c8157600080fd5b5035919050565b8051825260208082015173ffffffffffffffffffffffffffffffffffffffff908116828501526040808401518186015260608085015115158187015260808086015161012082890181905281517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690890152850151610140880184905280516101608901819052600096918201959194939192906101808a019088905b80821015614d6a578851805187168452888101518985015287810151888501528581015186850152840151848401529787019760a09092019160019190910190614d25565b505060a08901519650614da360a08b01888051151582526020810151602083015260408101516040830152606081015160608301525050565b9998505050505050505050565b602081526000610a786020830184614c88565b602081526000610a786020830184614bb9565b803573ffffffffffffffffffffffffffffffffffffffff81168114610fe357600080fd5b60008060408385031215614e0d57600080fd5b614e1683614dd6565b946020939093013593505050565b8015158114611ff557600080fd5b60008060408385031215614e4557600080fd5b614e4e83614dd6565b91506020830135614e5e81614e24565b809150509250929050565b600080600060608486031215614e7e57600080fd5b614e8784614dd6565b9250614e9560208501614dd6565b9150604084013590509250925092565b600060208284031215614eb757600080fd5b8135610a7881614e24565b600060808284031215614ed457600080fd5b50919050565b60008060408385031215614eed57600080fd5b614ef683614dd6565b9150602083013567ffffffffffffffff811115614f1257600080fd5b614f1e85828601614ec2565b9150509250929050565b600080600060408486031215614f3d57600080fd5b833567ffffffffffffffff80821115614f5557600080fd5b818601915086601f830112614f6957600080fd5b813581811115614f7857600080fd5b876020828501011115614f8a57600080fd5b6020928301989097509590910135949350505050565b600060208284031215614fb257600080fd5b610a7882614dd6565b60008083601f840112614fcd57600080fd5b50813567ffffffffffffffff811115614fe557600080fd5b6020830191508360208260051b85010111156118b657600080fd5b6000806000806040858703121561501657600080fd5b843567ffffffffffffffff8082111561502e57600080fd5b61503a88838901614fbb565b9096509450602087013591508082111561505357600080fd5b5061506087828801614fbb565b95989497509550505050565b60006020828403121561507e57600080fd5b813567ffffffffffffffff81111561509557600080fd5b61109684828501614ec2565b600080604083850312156150b457600080fd5b50508035926020909101359150565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015615136577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452615124858351614c88565b945092850192908501906001016150ea565b5092979650505050505050565b600080600080600080600060e0888a03121561515e57600080fd5b61516788614dd6565b965061517560208901614dd6565b95506040880135945060608801359350608088013560ff8116811461519957600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156151c957600080fd5b6151d283614dd6565b91506151e060208401614dd6565b90509250929050565b6000806000604084860312156151fe57600080fd5b83359250602084013567ffffffffffffffff81111561521c57600080fd5b61522886828701614fbb565b9497909650939450505050565b600181811c9082168061524957607f821691505b602082108103614ed4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000815461528f81615235565b600182811680156152a757600181146152da57615309565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0084168752821515830287019450615309565b8560005260208060002060005b858110156153005781548a8201529084019082016152e7565b50505082870194505b5050505092915050565b6000610a788284615282565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208083526000845461536281615235565b8084870152604060018084166000811461538357600181146153bb576153e9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506153e9565b896000528660002060005b858110156153e15781548b82018601529083019088016153c6565b8a0184019650505b509398975050505050505050565b60006154038285615282565b8351615413818360208801614b95565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109d7576109d761541c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361548f5761548f61541c565b5060010190565b808201808211156109d7576109d761541c565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126154de57600080fd5b83018035915067ffffffffffffffff8211156154f957600080fd5b6020019150600581901b36038213156118b657600080fd5b80820281158282048414176109d7576109d761541c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b601f821115611c0657600081815260208120601f850160051c810160208610156155ad5750805b601f850160051c820191505b81811015611ade578281556001016155b9565b67ffffffffffffffff8311156155e4576155e4615557565b6155f8836155f28354615235565b83615586565b6000601f84116001811461564a57600085156156145750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556156e0565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156156995786850135825560209485019460019092019101615679565b50868210156156d4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261576557600080fd5b830160208101925035905067ffffffffffffffff81111561578557600080fd5b8060051b36038213156118b657600080fd5b8183526000602080850194508260005b858110156157e05773ffffffffffffffffffffffffffffffffffffffff6157cd83614dd6565b16875295820195908201906001016157a7565b509495945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561581d57600080fd5b8260051b80836020870137939093016020019392505050565b600073ffffffffffffffffffffffffffffffffffffffff8085168352604060208401528061586385614dd6565b1660408401525060208301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261589f57600080fd5b830160208101903567ffffffffffffffff8111156158bc57600080fd5b8036038213156158cb57600080fd5b608060608501526158e060c0850182846156e7565b9150506158f06040850185615730565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080868503016080870152615926848385615797565b93506159356060880188615730565b93509150808685030160a08701525061594f8383836157eb565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261598f57600080fd5b83018035915067ffffffffffffffff8211156159aa57600080fd5b6020019150368190038213156118b657600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615a0d57615a0d6159cf565b500490565b600060208284031215615a2457600080fd5b5051919050565b600060208284031215615a3d57600080fd5b8151610a7881614e24565b60008351615a5a818460208801614b95565b610f0681840185615282565b6000615a728286615282565b8451615a82818360208901614b95565b61594f81830186615282565b600082615a9d57615a9d6159cf565b500690565b600081615ab157615ab161541c565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60008351615ae9818460208801614b95565b7f2052657175697265643a200000000000000000000000000000000000000000009083019081528351615b2381600b840160208801614b95565b01600b01949350505050565b7f206761732e2052657175697265643a2000000000000000000000000000000000815260008451615b67816010850160208901614b95565b7f206761732f726563697069656e74202b200000000000000000000000000000006010918401918201528451615ba4816021840160208901614b95565b7f206761732f54782e200000000000000000000000000000000000000000000000602192909101918201528351615be281602a840160208801614b95565b7f206d617820726563697069656e74732e00000000000000000000000000000000602a9290910191820152603a0195945050505050565b815167ffffffffffffffff811115615c3357615c33615557565b615c4781615c418454615235565b84615586565b602080601f831160018114615c9a5760008415615c645750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611ade565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015615ce757888601518255948401946001909101908401615cc8565b5085821015615d2357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060ff821660ff8103615d4957615d4961541c565b60010192915050565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818116838216019080821115612ed357612ed361541c565b60008351615d9c818460208801614b95565b835190830190615413818360208801614b95565b60008451615dc2818460208901614b95565b845190830190615dd6818360208901614b95565b8451910190615de9818360208801614b95565b019594505050505056fea2646970667358221220bf164ab27a6e986c8b955d0a65d80a4c4301fb9e3dbb0237ce75331b01fed53264736f6c6343000813003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000876bf80000000000000000000000000eb19ffee8e29420d405a2bdb65137c53cbbd096b000000000000000000000000e524ae868b899a9d3cf7259b2579affd66c468230000000000000000000000000000000000000000000000000000000000000013547269706c6520436f6e6669726d6174696f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025443000000000000000000000000000000000000000000000000000000000000

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

00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000876bf80000000000000000000000000eb19ffee8e29420d405a2bdb65137c53cbbd096b000000000000000000000000e524ae868b899a9d3cf7259b2579affd66c468230000000000000000000000000000000000000000000000000000000000000013547269706c6520436f6e6669726d6174696f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025443000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Triple Confirmation
Arg [1] : _symbol (string): TC
Arg [2] : _supply (uint256): 142000000
Arg [3] : _deployer (address): 0xeb19ffee8e29420d405a2bdb65137c53cbbd096b
Arg [4] : _guardian (address): 0xe524ae868b899a9d3cf7259b2579affd66c46823

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 000000000000000000000000000000000000000000000000000000000876bf80
Arg [3] : 000000000000000000000000eb19ffee8e29420d405a2bdb65137c53cbbd096b
Arg [4] : 000000000000000000000000e524ae868b899a9d3cf7259b2579affd66c46823
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [6] : 547269706c6520436f6e6669726d6174696f6e00000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [8] : 5443000000000000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

23379:119300:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28113:102;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;25993:28;;;;;;;;1506:25:1;;;1494:2;1479:18;25993:28:0;1360:177:1;41982:155:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;26918:34::-;;;:::i;:::-;;;;;;;:::i;95049:134::-;;;;;;:::i;:::-;;:::i;:::-;;;4749:14:1;;4742:22;4724:41;;4712:2;4697:18;95049:134:0;4584:187:1;111259:962:0;;;:::i;:::-;;25664:39;;;;;;26046:33;;;;;27996;;;;;;85872:833;;;;;;:::i;:::-;;:::i;95811:3691::-;;;;;;:::i;:::-;;:::i;110675:70::-;;;:::i;29793:663::-;;;:::i;32221:39::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;5728:42:1;5716:55;;;5698:74;;5686:2;5671:18;32221:39:0;5552:226:1;24574:34:0;;24607:1;24574:34;;;;;5955:4:1;5943:17;;;5925:36;;5913:2;5898:18;24574:34:0;5783:184:1;90157:366:0;;;;;;:::i;:::-;;:::i;111056:31::-;;;;;;29500:26;;;;;;;;;104221:267;;;;;;:::i;:::-;;:::i;100321:191::-;;;;;;:::i;:::-;;:::i;135193:6213::-;;;;;;:::i;:::-;;:::i;29533:29::-;;;;;;;;;103144:1009;;;;;;:::i;:::-;;:::i;45140:194::-;;;;;;:::i;:::-;;:::i;27002:36::-;;;;;;;;;;;;;;;;;;;;;93048:103;;;;;;:::i;:::-;93129:14;;93105:4;93129:14;;;:7;:14;;;;;;;93048:103;84306:718;;;;;;:::i;:::-;;:::i;25030:48::-;;;;;;110385:39;;;;;;:::i;:::-;;;;;;;;;;;;;;129397:526;;;;;;:::i;:::-;;:::i;:::-;;;;8040:25:1;;;8096:2;8081:18;;8074:34;;;;8013:18;129397:526:0;7866:248:1;32180:34:0;;;;;;:::i;:::-;;;;;;;;;;;;;;46851:181;;;;;;:::i;:::-;;:::i;45796:549::-;;;;;;:::i;:::-;;:::i;32150:23::-;;;;;;130756:4160;;;;;;:::i;:::-;;:::i;29569:29::-;;;;;;;;;26959:36;;;:::i;24879:48::-;;6741:7;24879:48;;111169:19;;;;;;87090:153;;;;;;:::i;:::-;;:::i;105415:313::-;;;;;;:::i;:::-;;:::i;104556:485::-;;;;;;:::i;:::-;;:::i;92330:594::-;;;;;;:::i;:::-;;:::i;127535:93::-;;;;;;:::i;:::-;;:::i;48023:229::-;;;;;;:::i;:::-;;:::i;25317:30::-;;;;;;48897:173;;;:::i;40626:624::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;88283:1570::-;;;;;;:::i;:::-;;:::i;142257:411::-;;;;;;:::i;:::-;;:::i;107977:1740::-;;;;;;:::i;:::-;;:::i;93296:937::-;;;;;;:::i;:::-;;:::i;100791:2163::-;;;;;;:::i;:::-;;:::i;27081:58::-;;;;;;;;;;;;;;;;;;;;;39890:123;;;:::i;120792:138::-;;;;;;:::i;:::-;;:::i;41348:531::-;;;;;;:::i;:::-;;:::i;119329:116::-;;;;;;:::i;:::-;;:::i;28113:102::-;28157:24;;:::i;:::-;28194:13;;;;;;;;;28201:6;28194:13;-1:-1:-1;28194:13:0;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28113:102;:::o;41982:155::-;42065:14;;:::i;:::-;42116:12;;;;:7;:12;;;;;;42105:24;;42116:12;;42105:10;:24::i;:::-;42098:31;41982:155;-1:-1:-1;;41982:155:0:o;26918:34::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;95049:134::-;95114:4;95138:37;95147:10;95159:7;95168:6;95138:8;:37::i;:::-;95131:44;95049:134;-1:-1:-1;;;95049:134:0:o;111259:962::-;111328:13;111318:7;:23;111907:22;;110866:119;;111907:22;;111923:4;;111907:22;:::i;:::-;;;;;;;;;;111998:7;;;;;;;;;;;;;;111805:397;;;;;14864:25:1;;;;14905:18;;14898:34;;;;111982:25:0;14948:18:1;;;14941:34;112055:13:0;14991:18:1;;;14984:34;112138:4:0;15034:19:1;;;15027:84;14836:19;;111805:397:0;;;;;;;;;;;;;111781:432;;111805:397;111781:432;;;;111762:16;:451;111259:962::o;85872:833::-;56835:36;56860:10;56835:24;:36::i;:::-;56886:28;;56813:112;;;;;;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;86088:14:0::1;::::0;86011:229:::1;::::0;86056:17;;86088:14:::1;;86117::::0;:47;::::1;;;-1:-1:-1::0;86150:14:0::1;::::0;86135:11:::1;::::0;86150:14:::1;86135:11:::0;;::::1;86150:14:::0;::::1;86135:29;;86117:47;86011:229;::::0;;;;::::1;::::0;;;;86180:6:::1;5752:2;86180:23;86011:229;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;86011:229:0;;;-1:-1:-1;;86011:229:0::1;;86205:6;5790:2;86205:23;;86011:229;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;:30:::1;:229::i;:::-;86618:14;::::0;86603:49:::1;::::0;::::1;::::0;;::::1;::::0;86618:14:::1;::::0;86603:49:::1;::::0;86618:14:::1;::::0;86603:49:::1;-1:-1:-1::0;86663:14:0::1;:34:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;85872:833::o;95811:3691::-;95930:4;95947:15;95965:28;95975:5;95982:10;95965:9;:28::i;:::-;95947:46;-1:-1:-1;96293:10:0;:19;;;;:43;;;;;96330:6;96316:10;:20;;96293:43;96289:3089;;;96641:14;;96637:108;;96694:10;96683:22;;;;:10;:22;;;;;;;;:34;;;;;96676:53;96637:108;96289:3089;;;97868:20;;;;97943:32;97998:31;97868:20;97998:19;:31::i;:::-;97907:141;;;;;;;;;:::i;:::-;;;;;;;;;;;;;97842:221;;;;;;;;;;;;;;:::i;:::-;;98627:14;98613:10;:28;98609:120;;98662:17;;;;;;;:10;:17;;;;;;;;98680:10;98662:29;;;;;;;:51;;98707:6;;98662:17;:51;;98707:6;;98662:51;:::i;:::-;;;;-1:-1:-1;;98609:120:0;99459:35;99469:5;99476:9;99487:6;99459:9;:35::i;:::-;99452:42;95811:3691;-1:-1:-1;;;;;95811:3691:0:o;110675:70::-;110726:10;110719:18;;;;:6;:18;;;;;110717:20;;110719:18;;;110717:20;;;:::i;:::-;;;;-1:-1:-1;110675:70:0:o;29793:663::-;29912:11;;;;29848:4;29904:20;;;:7;:20;;;;;;29848:4;;29890:34;;:11;:34;:::i;:::-;30325:14;;30310:11;;29865:59;;-1:-1:-1;30325:14:0;30310:11;;;30325:14;;30310:29;30306:106;;30385:14;;;;30377:23;;;;:7;:23;;;;;;30356:44;;;;:::i;:::-;;;30306:106;30431:17;29793:663;-1:-1:-1;29793:663:0:o;90157:366::-;56835:36;56860:10;56835:24;:36::i;:::-;56886:28;;56813:112;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;90421:28:0;6841:10:::1;90363:43:::0;::::1;;90341:119;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;90473:18:0::1;:42:::0;90157:366::o;104221:267::-;104336:4;104359:15;104377:30;104387:10;104399:7;104377:9;:30::i;:::-;104359:48;-1:-1:-1;104425:55:0;104434:10;104446:7;104455:24;104468:11;104359:48;104455:24;:::i;:::-;104425:8;:55::i;:::-;104418:62;104221:267;-1:-1:-1;;;;104221:267:0:o;100321:191::-;100492:10;100410:4;100472:31;;;:19;:31;;;;;;100440:64;;100459:11;;100472:31;;100440:18;:64::i;135193:6213::-;135366:26;135327:10;135305:98;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;135592:14:0;;;;:5;:14;:::i;:::-;135578:28;;:10;:28;;;:64;;;-1:-1:-1;135623:10:0;:19;;;;135578:64;135657:27;;135556:139;;;;;;;;;;;;;:::i;:::-;;135723:23;135761:28;135803:30;135820:5;135827;135803:16;:30::i;:::-;136006:20;;;;;;;:13;:20;;;;;:39;135708:125;;-1:-1:-1;135708:125:0;-1:-1:-1;136060:32:0;;135984:61;;135962:141;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;136217:17:0;:29;136167:79;;136149:5038;;137356:14;137373:16;;;;:5;:16;:::i;:::-;:23;-1:-1:-1;137695:29:0;;-1:-1:-1;137710:13:0;137373:23;137722:1;137710:13;:::i;:::-;137695:14;:29::i;:::-;137996:20;;;137987:6;137996:20;;;:13;:20;;;;;4635:1;137996:32;;;138073:708;138084:9;138080:1;:13;138073:708;;;138338:30;:28;:30::i;:::-;:65;;;;;138397:6;138393:1;:10;138338:65;:107;;;;-1:-1:-1;138436:9:0;138428:5;:1;138432;138428:5;:::i;:::-;:17;138338:107;138312:261;;;138488:20;;;;;;;:13;:20;;;;;138523:1;;4635;138488:32;:36;-1:-1:-1;;;;;;;135193:6213:0:o;138312:261::-;138720:45;138727:16;;;;:5;:16;:::i;:::-;138744:1;138727:19;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;138748:13;;;;:5;:13;:::i;:::-;138762:1;138748:16;;;;;;;:::i;:::-;;;;;;;138720:6;:45::i;:::-;138095:3;;;:::i;:::-;;;138073:708;;;136258:2534;;;136149:5038;;;138921:40;;138871:90;;138853:2334;;139143:63;139161:5;139168:4;139174:16;;;;:5;:16;:::i;:::-;139192:13;;;;:5;:13;:::i;:::-;139143:17;:63::i;:::-;139262:16;;;;:5;:16;:::i;:::-;139227:20;;;;;;;:13;:20;;;;;139262:23;;-1:-1:-1;4635:1:0;139227:32;;;:58;139223:105;;;139306:7;;135193:6213;;:::o;139223:105::-;138853:2334;;;139460:32;;139410:82;;139392:1795;;139666:147;139694:5;139718:4;139741:13;;;;:5;:13;:::i;:::-;4406:1;139741:22;;;;;:::i;:::-;;;;;;;139782:5;:16;;;;;;;;:::i;:::-;139666:9;:147::i;139392:1795::-;140063:28;;140013:78;;139995:1192;;140362:134;140386:5;140410:13;;;;:5;:13;:::i;:::-;4406:1;140410:22;;;;;:::i;:::-;;;;;;;140451:5;:13;;;;;;;;:::i;:::-;4443:1;140451:30;;;;;;;:::i;:::-;;;;;;;140362:5;:134::i;139995:1192::-;140628:31;;140578:81;;140560:627;;140832:111;140859:5;140883:4;140906:13;;;;:5;:13;:::i;:::-;4406:1;140906:22;;;;;:::i;:::-;;;;;;;140832:8;:111::i;:::-;140999:11;;140964:20;;;;;;;:13;:20;;;;;4635:1;140964:32;;140560:627;141139:36;;;;;;;141146:28;;141139:36;;;:::i;140560:627::-;141378:20;;;;;;;:13;:20;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;141371:27:0;135294:6112;;135193:6213;;:::o;103144:1009::-;103506:30;103516:10;103528:7;103506:9;:30::i;:::-;103540:1;103506:35;103502:450;;103908:10;103897:22;;;;:10;:22;;;;;;;;;:31;;;;;;;;;103890:50;103502:450;104117:6;:28;;104144:1;104117:28;;;104126:15;104117:28;104069:10;104058:22;;;;:10;:22;;;;;;;;;:31;;;;;;;;;4116:1;104058:43;:87;-1:-1:-1;;103144:1009:0:o;45140:194::-;57341:44;57374:10;57341:32;:44::i;:::-;57400:36;;57319:128;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;5177:2:0::1;45275:17:::0;::::1;45268:25;;;;:::i;:::-;45320:6;;45304;45311:5;45304:13;;;;;;;:::i;:::-;;::::0;:22:::1;::::0;;:13;:22:::1;:::i;84306:718::-:0;56283:11;;;;56380:10;56272:22;56406:20;;56343:94;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;84505:11:0::1;::::0;84431:184:::1;::::0;;;;::::1;::::0;;;::::1;::::0;84476:14;;84505:11:::1;::::0;;::::1;::::0;84531:14;;84431:184;84561:6:::1;5679:2;84561:20;84431:184;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;84431:184:0;;;-1:-1:-1;;84431:184:0::1;;84583:6;5714:2;84583:20;::::0;84431:184:::1;84820:14;::::0;84805:11:::1;::::0;84820:14:::1;::::0;;::::1;84805:11:::0;::::1;:29:::0;84801:111:::1;;84851:49;84869:14;84885;84851:17;:49::i;:::-;84949:11;::::0;84937:40:::1;::::0;::::1;::::0;;::::1;::::0;84949:11:::1;::::0;84937:40:::1;::::0;84949:11:::1;::::0;84937:40:::1;-1:-1:-1::0;84988:11:0::1;:28:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;84306:718::o;129397:526::-;129521:4;129536:7;129676:5;129708;129639:97;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;129607:148;;129639:97;129607:148;;;;;129852:18;;;;:5;:18;:::i;:::-;129813:76;;;;;;;;;:::i;:::-;;;;;;;;;;;;;129785:119;;;;;;129562:353;;;;129397:526;;;;;;:::o;46851:181::-;57341:44;57374:10;57341:32;:44::i;:::-;57400:36;;57319:128;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;46987:17:0::1;::::0;;;::::1;;::::0;;;:9:::1;:17;::::0;;;;:37;;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;46851:181::o;45796:549::-;57341:44;57374:10;57341:32;:44::i;:::-;57400:36;;57319:128;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;45969:8:0;46002:32;;::::1;45995:40;;;;:::i;:::-;46046:24;46061:8;46068:1;46061:4:::0;:8:::1;:::i;46046:24::-;46088:6;46083:255;46100:4;46096:1;:8;46083:255;;;46130:30;:28;:30::i;:::-;:39;;;;;46168:1;46164;:5;46130:39;:55;;;;-1:-1:-1::0;46181:4:0;46173:5:::1;:1:::0;46177::::1;46173:5;:::i;:::-;:12;46130:55;46126:102;;;46206:7;;;;46126:102;46242:24;46254:8;;46263:1;46254:11;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;46242;:24::i;:::-;;46306:17;;46324:1;46306:20;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;46281:9;:22;46291:8;;46300:1;46291:11;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;46281:22;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;46281:22:0;:45;;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;46106:3:::1;::::0;::::1;:::i;:::-;;;46083:255;;;;45944:401;45796:549:::0;;;;:::o;130756:4160::-;130875:10;130861:25;;;;:13;:25;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;131032:1:0;131006:14;;;;:5;:14;:::i;:::-;:28;;;131002:67;;130756:4160;:::o;131002:67::-;131561:28;131708:35;131725:10;131737:5;131708:16;:35::i;:::-;131629:10;131615:25;;;;:13;:25;;;;;131600:143;;;;132446:17;:29;131600:143;;-1:-1:-1;132396:79:0;;132378:2531;;132528:44;132561:10;132528:32;:44::i;:::-;132591:36;;132502:140;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;132746:13:0;;;;:5;:13;:::i;:::-;:20;-1:-1:-1;132685:16:0;;;;:5;:16;:::i;:::-;:81;;;;;-1:-1:-1;132785:6:0;5574:1;132785:24;;132659:165;;;;;;;;;;;;;;:::i;:::-;;130833:4083;130756:4160;:::o;132378:2531::-;132975:40;;132925:90;;132907:2002;;133129:13;;;;:5;:13;:::i;:::-;:20;-1:-1:-1;133068:16:0;;;;:5;:16;:::i;:::-;:81;;;;;-1:-1:-1;133168:6:0;5507:1;133168:27;;132907:2002;133353:32;;133303:82;;133285:1624;;133438:13;;;;:5;:13;:::i;:::-;133482:22;;-1:-1:-1;133462:1:0;133438:25;133412:107;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;133536:169:0;133573:10;133602:13;;;;:5;:13;:::i;:::-;4406:1;133602:22;;;;;:::i;:::-;;;;;;;133643:5;:16;;;;;;;;:::i;:::-;:23;;133685:5;133536:18;:169::i;:::-;130833:4083;130756:4160;:::o;133285:1624::-;133844:28;;133794:78;;133776:1133;;133927:13;;;;:5;:13;:::i;:::-;133971:22;;-1:-1:-1;133951:1:0;133927:25;133901:107;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;134247:176:0;134284:10;134313:13;;;;:5;:13;:::i;:::-;4406:1;134313:22;;;;;:::i;:::-;;;;;;;134354:5;:13;;;;;;;;:::i;:::-;4443:1;134354:30;;;;;;;:::i;:::-;;;;;;;134403:5;134247:18;:176::i;133776:1133::-;134631:31;;134681:28;;134573:89;;134547:177;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;134816:13:0;;;;:5;:13;:::i;:::-;134860:22;;-1:-1:-1;134840:1:0;134816:25;134790:107;;;;;;;;;;;;;:::i;26959:36::-;;;;;;;:::i;87090:153::-;56835:36;56860:10;56835:24;:36::i;:::-;56886:28;;56813:112;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;87201:14:0::1;:34:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;87090:153::o;105415:313::-;105614:27;105564:35;;;105542:110;;;;;;;;;;;;;:::i;:::-;;105663:57;105681:10;105693:5;105700:10;;105712:7;;105663:17;:57::i;104556:485::-;104674:4;104697:15;104715:30;104725:10;104737:7;104715:9;:30::i;:::-;104697:48;-1:-1:-1;104778:28:0;;;;104853;104900:31;104697:48;104900:19;:31::i;:::-;104821:125;;;;;;;;;:::i;:::-;;;;;;;;;;;;;104756:201;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;104975:58:0;104984:10;104996:7;105005:27;105018:14;105005:10;:27;:::i;92330:594::-;92391:4;92701:23;92713:10;92701:11;:23::i;:::-;:56;;;;92742:15;92754:2;92742:11;:15::i;:::-;92741:16;92701:56;:109;;;;92774:36;92807:2;92774:32;:36::i;:::-;92825:27;;92679:184;;;;;;;;;;;;;:::i;:::-;;92883:33;92893:10;92905:2;92909:6;92883:9;:33::i;127535:93::-;127585:35;127594:10;127606:5;127613:6;127585:8;:35::i;:::-;127535:93;:::o;48023:229::-;57341:44;57374:10;57341:32;:44::i;:::-;57400:36;;57319:128;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;48138:23:0::1;48148:12:::0;;;:7:::1;:12;::::0;;;;;;;;::::1;;48138:23:::0;;:9:::1;:23:::0;;;;;;48176:25;;48138:23:::1;;48137:24;48115:97;;;;;;;;;;;;;:::i;:::-;;48223:21;48230:8;48240:3;48223:6;:21::i;48897:173::-:0;49034:28;:26;:28::i;:::-;48897:173::o;40626:624::-;40737:16;40822:15;40794:13;;;;40772:76;;;;;;;;;;;;;:::i;:::-;;41048:11;;41041:4;:18;41037:162;;;41083:11;;;-1:-1:-1;41113:19:0;;;41109:79;;;41161:11;;41153:19;;41109:79;41216:26;41230:5;41237:4;41216:13;:26::i;88283:1570::-;57341:44;57374:10;57341:32;:44::i;:::-;57400:36;;57319:128;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;88652:19:0::1;88669:2;88652:14;:19;:::i;:::-;88686:24:::0;;88635:36;::::1;;88613:108;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89239:23:0;89186:38;;::::1;89164:109;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89516:18:0::1;89533:1;89516:14;:18;:::i;:::-;89549:29:::0;;89490:44;::::1;;89468:121;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;89725:10:0::1;:26:::0;;;89762:19:::1;:44:::0;;;89817:28:::1;:26;:28::i;142257:411::-:0;142372:31;;;;;142397:4;142372:31;;;5698:74:1;142335:5:0;;142312:13;;142372:16;;;;;;5671:18:1;;142372:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;142352:51;;142466:10;142437:40;;142445:5;142437:40;;;142452:12;142437:40;;;;1506:25:1;;1494:2;1479:18;;1360:177;142437:40:0;;;;;;;;142494:16;;142490:171;;142553:41;;;;;142569:10;142553:41;;;26229:74:1;26319:18;;;26312:34;;;142553:15:0;;;;;;26202:18:1;;142553:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;142613:21;;142527:122;;;;;;;;;;;;;:::i;107977:1740::-;108237:25;108207:15;108195:27;;;108173:100;;;;;;;;;;;;;:::i;:::-;;108286:15;108408:28;:26;:28::i;:::-;108664:13;;;;;;;:6;:13;;;;;:15;;106359:111;;108566:5;;108598:7;;108632:5;;108664:15;;:13;:15;;;:::i;:::-;;;;-1:-1:-1;108487:250:0;;;;;;26894:25:1;;;;26938:42;27016:15;;;26996:18;;;26989:43;27068:15;;;;27048:18;;;27041:43;27100:18;;;27093:34;27143:19;;;27136:35;27187:19;;;27180:35;;;26866:19;;108487:250:0;;;;;;;;;;;;108455:301;;;;;;108328:443;;;;;;;;27496:66:1;27484:79;;27588:1;27579:11;;27572:27;;;;27624:2;27615:12;;27608:28;27661:2;27652:12;;27226:444;108328:443:0;;;;;;;;;;;;;;108304:478;;108328:443;108304:478;;;;109244:27;;;;;;;;;27902:25:1;;;27975:4;27963:17;;27943:18;;;27936:45;;;;27997:18;;;27990:34;;;28040:18;;;28033:34;;;108304:478:0;-1:-1:-1;109244:27:0;;27874:19:1;;109244:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;109244:27:0;;;;;109286:23;;-1:-1:-1;109235:36:0;;;;;;;109213:107;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;109571:18:0;109537:19;;;109515:85;;;;;;;;;;;;;:::i;:::-;;109678:31;109687:5;109694:7;109703:5;109678:8;:31::i;:::-;;108162:1555;107977:1740;;;;;;;:::o;93296:937::-;94186:26;;;93403:4;94186:26;;;:19;:26;;;;;;94155:58;;94170:5;;94177:7;;94186:26;;94155:14;:58::i;:::-;:70;;;-1:-1:-1;;;93296:937:0:o;100791:2163::-;6899:2;100913:22;:54;;:132;;;;-1:-1:-1;101028:17:0;101002:43;;;100913:132;100894:210;;;-1:-1:-1;101077:27:0;;100894:210;101161:33;;100872:333;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;102204:10:0;102153:28;102184:31;;;:19;:31;;;;;;;;102244:46;;;;;;:281;;-1:-1:-1;102326:27:0;;;:184;;;102420:1;102397:20;:24;;;:94;;;;;102471:20;102446:45;;:22;:45;102397:94;102226:643;;;102769:46;102788:4;102794:20;102769:18;:46::i;:::-;102764:94;;102836:7;100791:2163;:::o;102764:94::-;-1:-1:-1;102901:10:0;102881:31;;;;:19;:31;;;;;:65;;;;;;;;;;;;;;;100791:2163::o;39890:123::-;39940:16;39976:29;39990:1;39993:11;;39976:13;:29::i;:::-;39969:36;;39890:123;:::o;120792:138::-;120874:48;120884:10;120896:5;120903:6;120911:10;;120874:9;:48::i;41348:531::-;41433:14;;:::i;:::-;41497:29;;;41466:28;41497:29;;;:19;:29;;;;;;;;;41544:327;;;;;;;41566:2;:12;;;;;;41544:327;;;;;;;;41616:17;;;:7;:17;;;;;;41544:327;;;;41648:19;;;:9;:19;;;;;;;;;41544:327;;;;;;41682:137;;;;;;;;41497:29;;;;41682:137;;;41497:29;41544:327;;;;;41682:137;;41748:56;41517:8;41497:29;41748:24;:56::i;:::-;41682:137;;41544:327;;;;41834:26;41851:8;41834:16;:26::i;:::-;41544:327;;41537:334;41348:531;-1:-1:-1;;;41348:531:0:o;119329:116::-;119396:41;119402:10;119414:6;119422:14;119396:5;:41::i;72405:2123::-;72719:18;;;;72532:4;72719:18;;;:10;:18;;;;;;;;:28;;;;;;;;;;;:50;;;4084:1;74000:40;;:45;;73996:117;;74062:24;;;;;;;;:16;:24;;;;;;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;73996:117;74198:18;;;;;;;;:10;:18;;;;;;;;:28;;;;;;;;;;;;;74241:15;4084:1;74198:40;;;:58;74463:35;;1506:25:1;;;74463:35:0;;1479:18:1;74463:35:0;;;;;;;;-1:-1:-1;74516:4:0;72405:2123;;;;;:::o;56600:158::-;56673:4;56697:26;56715:7;56566:14;;;56555:25;;;56566:14;;56555:25;;56465:123;56697:26;:53;;;-1:-1:-1;56283:11:0;;;56272:22;;;56283:11;;56272:22;56727:23;56185:117;83330:867;83573:1;83547:23;83559:10;83547:11;:23::i;:::-;83589:10;;;-1:-1:-1;83525:111:0;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;83715:10:0;;;;83671:29;;;;;;;;83649:112;;;;;;;;;;;;;:::i;:::-;;83778:15;83774:256;;;83979:24;;;;;;;:7;:24;;;;;;83885:133;;83916:15;;83950:10;;83885:12;:133::i;:::-;;83774:256;84116:30;;;;;;;:13;:30;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;84109:37:0;-1:-1:-1;64387:229:0;64477:13;64544:21;64558:6;64544:13;:21::i;:::-;64516:92;;;;;64580:6;;64516:92;;;:::i;:::-;;;;;;;;;;;;;64509:99;;64387:229;;;:::o;69874:743::-;70041:14;;;69996:4;70041:14;;;:7;:14;;;;;;:25;-1:-1:-1;70041:25:0;70081:32;70049:5;70081:25;:32::i;:::-;70019:105;;;;;;;;;;;;;;:::i;:::-;;70299:16;70311:3;70299:11;:16::i;:::-;:21;;:46;;;70324:21;70339:5;70324:14;:21::i;:::-;70295:99;;;70368:14;;;;;-1:-1:-1;70295:99:0;70481:14;;;;;;;:7;:14;;;;;:25;;70499:7;;70481:14;:25;;70499:7;;70481:25;:::i;:::-;;;;-1:-1:-1;;70517:12:0;;;;;;;:7;:12;;;;;:23;;70533:7;;70517:12;:23;;70533:7;;70517:23;:::i;:::-;;;;;;;;70574:3;70558:29;;70567:5;70558:29;;;70579:7;70558:29;;;;1506:25:1;;1494:2;1479:18;;1360:177;79237:863:0;79446:10;79366:15;79429:28;;;:16;:28;;;;;;;;79400:57;;;;;;;;;;;;;;;;;79366:15;;79400:57;;79429:28;79400:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79468:40;79506:1;79487:9;:16;79483:1;:20;;;;:::i;:::-;:24;;;;:::i;79468:40::-;79673:6;79668:199;79685:9;:16;79681:1;:20;79668:199;;;79728:65;79744:9;79754:1;79744:12;;;;;;;;:::i;:::-;;;;;;;79758;79772:20;79728:15;:65::i;:::-;79723:133;;79814:17;;;;79723:133;79703:3;;;:::i;:::-;;;79668:199;;;;79892:4;79879:17;;79987:12;79982:81;;80040:10;80023:28;;;;:16;:28;;;;;80016:35;;;:::i;:::-;80075:17;79237:863;;;;:::o;67182:1443::-;68007:17;68063:8;;;:::i;:::-;;;;68050:10;;:21;;;;:::i;:::-;68027:19;;:45;;;;:::i;:::-;68007:65;-1:-1:-1;68124:3:0;68102:19;68107:14;68102:2;:19;:::i;:::-;:25;;;;:::i;:::-;68087:12;:40;68083:113;;;68181:3;68159:19;68164:14;68159:2;:19;:::i;:::-;:25;;;;:::i;:::-;68144:40;;68083:113;68418:12;68406:9;:24;68477:27;68523:28;68538:12;68523:14;:28::i;:::-;68445:161;;;;;;68570:21;;68445:161;;;:::i;:::-;;;;;;;;;;;;;68384:233;;;;;;;;;;;;;;:::i;57639:125::-;57701:4;57747:9;57725:19;;:31;57718:38;;57639:125;:::o;49456:2301::-;50588:1;50564:21;50576:8;50564:11;:21::i;:::-;:25;:1072;;;;-1:-1:-1;50928:17:0;;;;;;;:7;:17;;;;;;:22;:55;;;;-1:-1:-1;50975:8:0;;50928:55;50638:983;;;;51558:1;51552:3;:7;:50;;;;;51591:11;;51584:3;:18;;51552:50;51651:16;;50187:1491;;;;;;;;;;;;;:::i;:::-;;51726:23;51735:8;51745:3;51726:8;:23::i;74838:1666::-;75030:11;75059:20;75030:11;75059:14;:20::i;:::-;75126:6;75147:10;75143:58;;;-1:-1:-1;75165:21:0;;;;;;;:13;:21;;;;;4635:1;75165:33;;75143:58;75225:1;75211:11;75331:781;75342:4;75338:1;:8;75331:781;;;75390:10;:61;;;;;75421:30;:28;:30::i;:::-;75390:92;;;;;75476:6;75472:1;:10;75390:92;:125;;;;-1:-1:-1;75511:4:0;75503:5;:1;75507;75503:5;:::i;:::-;:12;75390:125;75550:5;75368:203;75774:46;75784:6;75792:11;;75804:1;75792:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;75808:8;;75817:1;75808:11;;;;;;;:::i;:::-;;;;;;;75774:9;:46::i;:::-;;76089:8;;76098:1;76089:11;;;;;;;:::i;:::-;;;;;;;76079:21;;;;;:::i;:::-;;-1:-1:-1;75348:3:0;;;:::i;:::-;;;75331:781;;;76128:10;76124:133;;;76155:21;;;;;;;:13;:21;;;;;76187:6;;4662:1;76155:28;;:38;;;;;;;:::i;:::-;;;;-1:-1:-1;;76208:21:0;;;;;;;:13;:21;;;;;76244:1;;4635;76208:33;:37;76124:133;76273:23;;;76269:228;;76353:6;76318:167;;;76378:10;:92;;76464:6;76378:92;;;76412:21;;;;;;;:13;:21;;;;;4662:1;76412:28;;76378:92;76318:167;;1506:25:1;;;1494:2;1479:18;76318:167:0;;;;;;;76269:228;75007:1497;;;;74838:1666;;;;;;:::o;119536:1162::-;119708:11;119737:47;119756:6;119764:7;119708:11;119779:4;119737:18;:47::i;:::-;119797:13;119821:6;119844:10;119840:107;;;-1:-1:-1;;119875:21:0;;;;;;;:13;:21;;;;;4635:1;119875:33;;;119840:107;119970:4;119966:1;:8;119959:540;;;120018:10;:61;;;;;120049:30;:28;:30::i;:::-;120018:94;;;;;120104:8;120100:1;:12;120018:94;:127;;;;-1:-1:-1;120141:4:0;120133:5;:1;120137;120133:5;:::i;:::-;:12;120018:127;120180:5;119996:205;120445:42;120455:6;120463:11;;120475:1;120463:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;120479:7;120445:9;:42::i;:::-;-1:-1:-1;119976:3:0;;;:::i;:::-;;;119959:540;;;120511:60;120520:6;120528:10;120540:1;120543;120557:12;120561:8;120543:1;120557:12;:::i;:::-;120546:24;;:7;:24;:::i;:::-;120511:8;:60::i;:::-;-1:-1:-1;120588:23:0;;;120584:107;;120633:46;;;;120650:28;120660:11;120650:7;:28;:::i;:::-;120633:46;;1506:25:1;;;1494:2;1479:18;120633:46:0;;;;;;;120584:107;119685:1013;;;119536:1162;;;;;:::o;113238:5992::-;113358:58;113377:6;113385:7;113394:15;113411:4;113358:18;:58::i;:::-;113463:13;113819:11;;113833:1;113819:15;;;;:::i;:::-;113547:234;;;113590:11;113547:234;;;29176:19:1;113628:15:0;29211:12:1;;;29204:28;;;;113670:12:0;29248::1;;;29241:28;29285:12;;;29278:28;;;29322:13;;;29315:29;;;29360:13;;113547:234:0;;;;;;;;;;;;113515:285;;;;;;113492:323;;:343;;;;:::i;:::-;113463:372;-1:-1:-1;113880:15:0;114234:19;:15;114252:1;114234:19;:::i;:::-;114019:16;114034:1;114019:12;:16;:::i;:::-;114009:27;114082:12;:8;114093:1;114082:12;:::i;:::-;114063:32;;:15;:32;:::i;:::-;114122:9;113966:230;;;;;;29714:19:1;;;;29749:12;;29742:28;;;;29786:12;;;29779:28;29823:12;;;29816:28;;;29860:13;;113966:230:0;;;;;;;;;;;;113934:281;;;;;;113911:319;;:343;;;;:::i;:::-;113880:374;-1:-1:-1;114299:18:0;114441:16;114456:1;114441:12;:16;:::i;:::-;114526:11;;114518:20;;;;:7;:20;;;;;;114431:27;;;114485:6;;114518:20;;114577:1;114565:9;:13;;;;:::i;:::-;114388:285;;;;;;30153:19:1;;;;30191:66;30295:2;30291:15;;;30287:24;;30273:12;;;30266:46;;;;30346:15;;;;30342:24;30328:12;;;30321:46;30383:12;;;30376:28;30420:13;;;30413:29;;;30458:13;;;30451:29;;;30496:13;;114388:285:0;;;;;;;;;;;;;114356:336;;114388:285;114356:336;;;;;-1:-1:-1;114757:17:0;114773:1;114356:336;114757:17;:::i;:::-;114778:1;114757:22;114753:65;;114796:10;;;:::i;:::-;;;114753:65;114832:17;114848:1;114832:13;:17;:::i;:::-;114853:1;114832:22;114828:67;;114871:12;;;:::i;:::-;;;114828:67;114909:17;114925:1;114909:13;:17;:::i;:::-;114930:1;114909:22;114905:65;;114948:10;;;:::i;:::-;;;114905:65;114984:18;115000:2;114984:13;:18;:::i;:::-;115006:1;114984:23;114980:68;;115024:12;;;:::i;:::-;;;114980:68;115073:11;;115062:8;:22;115058:78;;;115113:11;;115101:23;;;;:::i;:::-;;;115058:78;115163:11;;115150:10;:24;115146:82;;;115205:11;;115191:25;;;;:::i;:::-;;;115146:82;115289:8;115301:1;115289:13;115285:56;;115319:10;;;:::i;:::-;;;115285:56;115355:10;115369:1;115355:15;115351:60;;115387:12;;;:::i;:::-;;;115351:60;115439:8;;115423:13;;115538:3390;115549:15;115545:1;:19;115538:3390;;;115666:30;:28;:30::i;:::-;:56;;;;;115721:1;115717;:5;115666:56;:100;;;;-1:-1:-1;115751:15:0;115743:5;:1;115747;115743:5;:::i;:::-;:23;115666:100;115801:5;115644:178;116020:11;;116008:9;:23;116004:88;;;116065:11;;116052:24;;;;:::i;:::-;;;116004:88;116817:8;116804:9;:21;:30;;;;;116833:1;116829;:5;116804:30;116800:912;;;116871:8;116859;:20;116855:155;;116904:10;;;:::i;:::-;;;116855:155;;;116980:10;;;:::i;:::-;;;116855:155;117034:8;117046:1;117034:13;117030:81;;117083:8;117072:19;;117030:81;117146:11;;117135:8;:22;117131:357;;;117193:12;117204:1;117193:8;:12;:::i;:::-;117182:23;;117131:357;117520:8;117508:20;;116800:912;118317:18;;;;:7;:18;;;;;;118256:128;;118288:6;;118317:18;;118358:7;118256:9;:128::i;:::-;118233:644;;118814:11;;;:::i;:::-;;-1:-1:-1;118844:17:0;;;:::i;:::-;;;118233:644;118893:23;118906:10;118893:23;;:::i;:::-;;-1:-1:-1;115566:3:0;;;:::i;:::-;;;115538:3390;;;119166:56;119175:6;119183:5;;;119207:13;119211:9;119207:1;:13;:::i;:::-;119196:25;;:7;:25;:::i;119166:56::-;;113347:5883;;;;;;;113238:5992;;;:::o;121172:6229::-;121290:37;121305:21;;121290:14;:37::i;:::-;121374:13;121403:10;:96;;121478:21;;;;;;;:13;:21;;;;;;121403:96;;;121429:21;;;;;;;:13;:21;;;;;4635:1;121429:33;;121403:96;121374:125;;121753:8;121765:1;121753:13;121749:56;;121783:10;;;:::i;:::-;;;121749:56;121908:8;121899:6;121971:22;121985:7;121971:13;:22::i;:::-;121953:15;;;;;;;:7;:15;;;;;;:40;;;;:::i;:::-;121948:46;;:1;:46;:::i;:::-;121927:67;;122005:14;122030:18;122136:2879;122148:13;122143:1;:18;122136:2879;;122407:30;:28;:30::i;:::-;:66;;;;;122462:11;;122458:1;:15;122407:66;:99;;;;;122498:8;122494:1;:12;122407:99;:137;;;;;122531:13;122527:1;:17;122407:137;122579:5;122385:215;122987:11;;122971:13;:27;122967:442;;;123285:11;;123281:1;:15;123321:5;123277:69;123382:11;;123366:27;;122967:442;-1:-1:-1;123897:10:0;;;;:7;:10;;;;;;;;123947:120;123979:6;123897:10;124041:7;123947:9;:120::i;:::-;123924:1062;;124328:14;;;124345:1;124328:14;;;:2;:14;;;;;;:18;124324:618;;124371:11;;;:::i;:::-;;-1:-1:-1;124405:3:0;;;:::i;:::-;;;124844:11;;124828:13;:27;124824:99;;;124884:15;;;:::i;:::-;;;124824:99;122136:2879;;123924:1062;125000:3;;;:::i;:::-;;;122136:2879;;;125216:18;125253:20;125265:8;125253:9;:20;:::i;:::-;125249:1;:24;125245:108;;;125332:8;125316:13;125320:9;125316:1;:13;:::i;:::-;:24;;;;:::i;:::-;125305:36;;:7;:36;:::i;:::-;125289:52;;125245:108;125365:125;125388:6;125409:10;125434:1;125450;125466:13;125365:8;:125::i;:::-;;125724:10;125719:266;;125836:17;;125832:102;;125874:27;;;;;;;:19;:27;;;;;:44;;125905:13;;125874:27;:44;;125905:13;;125874:44;:::i;:::-;;;;-1:-1:-1;;125832:102:0;125948:21;;;;;;;:13;:21;;;;;:25;;;125719:266;126315:11;;126311:1;:15;126307:54;;;126343:7;;;;;;121172:6229;;;:::o;126307:54::-;126827:10;126823:114;;;126859:45;;;126875:21;;;;:13;:21;;;;;126859:45;;4662:1;126875:28;;126859:45;;1506:25:1;;;1494:2;1479:18;126859:45:0;;;;;;;126919:7;;;;;;121172:6229;;;:::o;126823:114::-;127124:44;;;127140:27;;;;:19;:27;;;;;;;;;;127124:44;;1506:25:1;;;127124:44:0;;1479:18:1;127124:44:0;;;;;;;-1:-1:-1;;;127243:21:0;;;;;;;;:13;:21;;;;;;;;127267:1;127243:25;;127366:19;:27;;;;;127359:34;-1:-1:-1;;;;;121172:6229:0:o;57084:176::-;57165:4;57189:26;57207:7;57054:14;;;57043:25;;;57054:14;;57043:25;;56953:123;57189:26;:63;;;;57219:33;57244:7;57219:24;:33::i;63061:871::-;63147:15;;;63120:8;63147:15;;;:2;:15;;;;;;63177:7;;;;:38;;;63188:27;63203:11;63188:14;:27::i;:::-;63173:81;;;63061:871;;;:::o;63173:81::-;63823:11;;63821:13;;;;;:::i;:::-;;;;;-1:-1:-1;63845:12:0;;;;:7;:12;;;;;;;;:26;;;;;;;;;;;;;;63882:15;;;:2;:15;;;;;;:21;;;-1:-1:-1;63821:13:0;63061:871::o;65137:1653::-;65700:25;65710:15;65700:7;:25;:::i;:::-;65681:15;;;;;;;:7;:15;;;;;;:44;;66052:33;65689:6;66052:25;:33::i;:::-;66136:46;66156:25;66166:15;66156:7;:25;:::i;:::-;66136:19;:46::i;:::-;66020:177;;;;;;;;;:::i;:::-;;;;;;;;;;;;;65659:549;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;66554:26:0;66520:19;66498:93;;;;;;;;;;;;;:::i;:::-;;66704:19;66700:83;;;66740:31;66755:15;66740:14;:31::i;7454:838::-;7516:4;8011:21;;7900:66;8239:25;;;;;;:45;;-1:-1:-1;;8268:16:0;;;8232:52;-1:-1:-1;;7454:838:0:o;55032:565::-;55181:25;55195:10;;55181:13;:25::i;:::-;55145:19;;55128:36;;:14;:36;:::i;:::-;55127:79;;;;:::i;:::-;55089:21;:117;55348:10;;55333:26;;:14;:26::i;:::-;55416:35;55431:19;;55416:14;:35::i;:::-;55500:37;55515:21;;55500:14;:37::i;:::-;55264:325;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;55227:21;;:362;;:21;:362;:::i;37990:1526::-;38095:26;38178:6;38166:9;38170:5;38166:1;:9;:::i;:::-;:18;;;;:::i;:::-;38152:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;38140:45:0;-1:-1:-1;38196:7:0;38266:6;38252:1228;38279:5;38274:1;:10;38252:1228;;39457:10;;;;:7;:10;;;;;;39446:22;;39457:10;;39446;:22::i;:::-;39428:9;39438:4;;;;:::i;:::-;;;39428:15;;;;;;;;:::i;:::-;;;;;;:40;;;;38286:3;;;;:::i;:::-;;;38252:1228;;;;39492:16;37990:1526;;;;:::o;112498:182::-;112553:7;112594;;112577:13;:24;112573:66;;112605:31;:29;:31::i;:::-;-1:-1:-1;112656:16:0;;;112498:182::o;76705:2438::-;76859:32;;:::i;:::-;77528:7;77523:108;4020:1;77537:12;;;;77523:108;;;77588:18;;;;;;;;:10;:18;;;;;;;;:28;;;;;;;;;:31;;;;;;;;;;:::i;:::-;;;77571:11;77583:1;77571:14;;;;;;;;;:::i;:::-;;;;:48;77551:3;;;:::i;:::-;;;77523:108;;;-1:-1:-1;78265:23:0;;;;78221:14;;78238:24;78242:20;4084:1;78238:24;:::i;:::-;:50;;;;;;:::i;:::-;78221:67;;78315:15;78303:9;:27;78299:117;;;78377:27;78389:15;78377:9;:27;:::i;:::-;78347;;;:57;78299:117;78915:1;78892:20;:24;;;:82;;;;-1:-1:-1;78946:23:0;;;;:28;78892:82;:144;;;;-1:-1:-1;79004:27:0;;;;:32;78892:144;78874:231;;;4052:1;79063:30;;78874:231;79117:18;76705:2438;;;;;:::o;34671:2494::-;34963:26;;;34934;34963;;;:16;:26;;;;;;;;34934:55;;;;;;;;;;;;;;;;;34810:31;;34934:26;:55;;34963:26;34934:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;35319:16:0;;34934:55;;-1:-1:-1;35319:16:0;;-1:-1:-1;;;35447:28:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35447:28:0;;;;;;;;;;;;;;;;;35431:44;;35631:6;35626:1499;35643:12;35639:1;:16;35626:1499;;;35816:16;35835:9;35845:1;35835:12;;;;;;;;:::i;:::-;;;;;;;35816:31;;36129;36180:138;36217:8;36248;36279:20;36180:14;:138::i;:::-;36895:218;;;;;;;;;;;;;36949:22;;36895:218;;;;;;;;36990:22;;;36895:218;;;;;37031:26;;;;36895:218;;;;37076:22;;;;36895:218;;;;36876:16;;36129:189;;-1:-1:-1;36895:218:0;36876:13;;36890:1;;36876:16;;;;;;:::i;:::-;;;;;;:237;;;;35662:1463;;35657:3;;;;:::i;:::-;;;35626:1499;;;;37137:20;;34671:2494;;;;:::o;37411:323::-;37493:17;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37493:17:0;37530:196;;;;;;;;37555:21;37567:8;37555:11;:21::i;:::-;37530:196;;;;37591:23;;;;;;;;;:13;37530:196;37591:23;;;;;;;;37530:196;;;;37629:29;;;:19;:29;;;;;;37530:196;;;;37673:23;;;:13;:23;;;:42;37530:196;;;;;;;;-1:-1:-1;37523:203:0;37411:323::o;10021:1430::-;10106:13;10221:6;10231:1;10221:11;10217:60;;-1:-1:-1;;10256:9:0;;;;;;;;;;;;;;;;;;10021:1430::o;10217:60::-;10494:13;10482:26;;10423:19;10693:30;10482:26;10693:14;:30::i;:::-;10664:59;-1:-1:-1;11044:18:0;;11040:203;;11079:153;6785:18;6801:2;6741:7;6785:18;:::i;:::-;11086:14;:34;11079:153;;;11192:9;;;;;;;;;;;;;;;;;11203:12;11178:38;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;11122:20:0;11140:2;11122:20;;:::i;:::-;;;11079:153;;;11341:38;11356:22;6741:7;11356:6;:22;:::i;:::-;11341:14;:38::i;:::-;11394:11;;;;;;;;;;;;;;;;;11420:12;11313:130;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;11306:137;;;;10021:1430;;;:::o;64017:266::-;64248:15;;;;;;;:7;:15;;;;;;64116:13;;64183:30;;64228:36;;:19;:36::i;:::-;64155:120;;;;;;;;;:::i;69043:274::-;69107:4;69201:22;;;;;:66;;-1:-1:-1;69240:27:0;;;69260:6;69240:27;69201:66;:108;;;-1:-1:-1;69284:25:0;;;69304:4;69284:25;69181:128;69043:274;-1:-1:-1;;69043:274:0:o;80204:2758::-;80357:15;80462:30;:28;:30::i;:::-;80509:17;80458:89;-1:-1:-1;80572:4:0;81340:1364;;;;81961:10;81997:1;81950:22;;;:10;:22;;;;;;;;;:32;;;;;;;;;4116:1;81950:44;;:48;:308;;;;82257:1;82102:140;82139:10;82172:8;82203:20;82102:14;:140::i;:::-;:152;:156;81950:308;82293:17;81928:406;82619:10;82608:22;;;;:10;:22;;;;;;;;;:32;;;;;;;;;82601:51;82667:17;;81340:1364;82897:10;82886:22;;;;:10;:22;;;;;;;;;:32;;;;;;;;;-1:-1:-1;;;;;;;;;;;;82879:39:0;-1:-1:-1;8389:653:0;8476:13;8591:7;8602:1;8591:12;8587:61;;-1:-1:-1;;8627:9:0;;;;;;;;;;;;;;;;;;8389:653::o;8587:61::-;8672:7;8658:11;8714:84;8721:11;;8714:84;;8749:10;;;:::i;:::-;;-1:-1:-1;8774:12:0;8784:2;8774:12;;:::i;:::-;;;8714:84;;;8808:21;8842:8;8832:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8832:19:0;;8808:43;;8862:137;8869:12;;8862:137;;8944:12;8954:2;8944:7;:12;:::i;:::-;8934:23;;:2;:23;:::i;:::-;8921:38;;8898:8;8907:10;;;:::i;:::-;;;;8898:20;;;;;;;;:::i;:::-;;;;:61;;;;;;;;;;-1:-1:-1;8974:13:0;8985:2;8974:13;;:::i;:::-;;;8862:137;;52372:2560;52856:23;52866:12;;;:7;:12;;;;;;;;;;;52856:23;;:9;:23;;;;;;;;52852:40;;;52372:2560;;:::o;52852:40::-;52940:3;52947:1;52940:8;52936:630;;53070:19;;;;;;;:9;:19;;;;;;;;53066:36;;;52372:2560;;:::o;53066:36::-;53441:11;;;52173:12;;;;52165:21;52173:12;;;:2;:12;;;;;;;;;;52165:21;;;:7;:21;;;;;;;;52201:12;;;;;;;;;;52228:16;;;;;;;;;;;;51997:285;;;;;;;;;;;;;;;;;;;52165:21;;;;51997:285;;;;;;;;;;;53483:13;;52165:7;;:21;53483:13;;;:::i;:::-;;;;-1:-1:-1;53475:22:0;;;;;;;;;;;;;;-1:-1:-1;53475:22:0;;;53468:29;;;;;;;53519:12;;;;;;:2;:12;;;;;53512:19;;;;-1:-1:-1;52372:2560:0:o;52936:630::-;52173:12;;;;52165:21;52173:12;;;:2;:12;;;;;;;;;;52165:21;;;:7;:21;;;;;;;52201:12;;;;;;;;;;52228:16;;;;;;;;;;;;;51997:285;;;;;;;;;;;;;;;;;;;;;;52165:21;;;;51997:285;;;130756:4160::o;127720:659::-;127895:4;127922:10;127918:384;;;127953:17;;127949:103;;127991:21;;;;;;;:13;:21;;;;;128023:13;;4662:1;127991:28;;:45;;;;;;;:::i;:::-;;;;-1:-1:-1;;127949:103:0;128070:13;;128066:98;;128104:21;;;;;;;:13;:21;;;;;128139:9;;4692:1;128104:31;;:44;;;;;;;:::i;:::-;;;;-1:-1:-1;;128066:98:0;128192:21;;;;;;;:13;:21;;;;;4635:1;128192:33;;:38;;;4692:1;128259:31;;;-1:-1:-1;127918:384:0;128322:6;128317:27;;;128330:13;128317:27;;;;1506:25:1;;1494:2;1479:18;;1360:177;128317:27:0;;;;;;;;-1:-1:-1;128362:9:0;;127720:659;-1:-1:-1;;;;127720:659:0:o;60629:1983::-;60759:10;61088;61078:20;;:6;:20;;;:58;;;-1:-1:-1;61115:21:0;;;;;;;:9;:21;;;;;;;;61078:58;:101;;;;61153:26;61168:10;61153:14;:26::i;:::-;61245:12;60790:479;61694:19;;;61673:18;61694:19;;;:7;:19;;;;;;61728:18;;:44;;;;;61771:1;61750:18;;:22;61728:44;61724:150;;;61789:23;61798:10;61810:1;61789:8;:23::i;:::-;61850:12;;;61724:150;62104:23;62116:10;62104:11;:23::i;:::-;62100:68;;;62144:12;;;62100:68;62393:18;;62376:13;:35;62372:113;;62435:38;62445:6;62453:10;62465:7;62435:9;:38::i;:::-;62428:45;;;;;9597:165;9658:4;9679:8;9691:1;9679:13;9675:54;;-1:-1:-1;9716:1:0;;9597:165;-1:-1:-1;9597:165:0:o;9675:54::-;-1:-1:-1;9746:8:0;9597:165::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;14:250:1;99:1;109:113;123:6;120:1;117:13;109:113;;;199:11;;;193:18;180:11;;;173:39;145:2;138:10;109:113;;;-1:-1:-1;;256:1:1;238:16;;231:27;14:250::o;269:330::-;311:3;349:5;343:12;376:6;371:3;364:19;392:76;461:6;454:4;449:3;445:14;438:4;431:5;427:16;392:76;:::i;:::-;513:2;501:15;518:66;497:88;488:98;;;;588:4;484:109;;269:330;-1:-1:-1;;269:330:1:o;604:751::-;793:2;845:21;;;764:4;;952;937:20;;818:18;;;980:6;764:4;1014:312;1028:4;1025:1;1022:11;1014:312;;;1115:66;1103:9;1095:6;1091:22;1087:95;1082:3;1075:108;1206:40;1239:6;1230;1224:13;1206:40;:::i;:::-;1196:50;-1:-1:-1;1304:12:1;;;;1269:15;;;;1048:1;1041:9;1014:312;;;-1:-1:-1;1343:6:1;;604:751;-1:-1:-1;;;;;;604:751:1:o;1542:180::-;1601:6;1654:2;1642:9;1633:7;1629:23;1625:32;1622:52;;;1670:1;1667;1660:12;1622:52;-1:-1:-1;1693:23:1;;1542:180;-1:-1:-1;1542:180:1:o;2011:1622::-;2116:12;;2104:25;;2148:4;2187:14;;;2181:21;2221:42;2293:21;;;2279:12;;;2272:43;2334:4;2374:14;;;2368:21;2354:12;;;2347:43;2409:4;2463:14;;;2457:21;2450:29;2443:37;2429:12;;;2422:59;2500:4;2541:14;;;2535:21;2089:6;2572:12;;;2565:24;;;2657:21;;2680:64;2653:92;2639:12;;;2632:114;2783:23;;2777:30;2832:3;2823:13;;2816:25;;;2890:21;;2619:3;2610:13;;2920:20;;;2061:3;;2994:23;;;;2148:4;;2334;2221:42;;2500:4;2967:3;2958:13;;;2061:3;;3045:438;3059:6;3056:1;3053:13;3045:438;;;3118:13;;3162:9;;3158:18;;3144:33;;3219:11;;;3213:18;3197:14;;;3190:42;3274:11;;;3268:18;3252:14;;;3245:42;3329:11;;;3323:18;3307:14;;;3300:42;3384:11;;3378:18;3362:14;;;3355:42;3458:15;;;;3430:4;3419:16;;;;3081:1;3074:9;;;;;3045:438;;;3049:3;;3531:4;3524:5;3520:16;3514:23;3492:45;;3546:60;3600:4;3595:3;3591:14;3575;1823:5;1817:12;1810:20;1803:28;1798:3;1791:41;1881:4;1874:5;1870:16;1864:23;1857:4;1852:3;1848:14;1841:47;1937:4;1930:5;1926:16;1920:23;1913:4;1908:3;1904:14;1897:47;1993:4;1986:5;1982:16;1976:23;1969:4;1964:3;1960:14;1953:47;;;1727:279;3546:60;3622:5;2011:1622;-1:-1:-1;;;;;;;;;2011:1622:1:o;3638:256::-;3815:2;3804:9;3797:21;3778:4;3835:53;3884:2;3873:9;3869:18;3861:6;3835:53;:::i;3899:220::-;4048:2;4037:9;4030:21;4011:4;4068:45;4109:2;4098:9;4094:18;4086:6;4068:45;:::i;4124:196::-;4192:20;;4252:42;4241:54;;4231:65;;4221:93;;4310:1;4307;4300:12;4325:254;4393:6;4401;4454:2;4442:9;4433:7;4429:23;4425:32;4422:52;;;4470:1;4467;4460:12;4422:52;4493:29;4512:9;4493:29;:::i;:::-;4483:39;4569:2;4554:18;;;;4541:32;;-1:-1:-1;;;4325:254:1:o;4776:118::-;4862:5;4855:13;4848:21;4841:5;4838:32;4828:60;;4884:1;4881;4874:12;4899:315;4964:6;4972;5025:2;5013:9;5004:7;5000:23;4996:32;4993:52;;;5041:1;5038;5031:12;4993:52;5064:29;5083:9;5064:29;:::i;:::-;5054:39;;5143:2;5132:9;5128:18;5115:32;5156:28;5178:5;5156:28;:::i;:::-;5203:5;5193:15;;;4899:315;;;;;:::o;5219:328::-;5296:6;5304;5312;5365:2;5353:9;5344:7;5340:23;5336:32;5333:52;;;5381:1;5378;5371:12;5333:52;5404:29;5423:9;5404:29;:::i;:::-;5394:39;;5452:38;5486:2;5475:9;5471:18;5452:38;:::i;:::-;5442:48;;5537:2;5526:9;5522:18;5509:32;5499:42;;5219:328;;;;;:::o;6154:241::-;6210:6;6263:2;6251:9;6242:7;6238:23;6234:32;6231:52;;;6279:1;6276;6269:12;6231:52;6318:9;6305:23;6337:28;6359:5;6337:28;:::i;6400:159::-;6463:5;6508:3;6499:6;6494:3;6490:16;6486:26;6483:46;;;6525:1;6522;6515:12;6483:46;-1:-1:-1;6547:6:1;6400:159;-1:-1:-1;6400:159:1:o;6564:435::-;6661:6;6669;6722:2;6710:9;6701:7;6697:23;6693:32;6690:52;;;6738:1;6735;6728:12;6690:52;6761:29;6780:9;6761:29;:::i;:::-;6751:39;;6841:2;6830:9;6826:18;6813:32;6868:18;6860:6;6857:30;6854:50;;;6900:1;6897;6890:12;6854:50;6923:70;6985:7;6976:6;6965:9;6961:22;6923:70;:::i;:::-;6913:80;;;6564:435;;;;;:::o;7004:666::-;7084:6;7092;7100;7153:2;7141:9;7132:7;7128:23;7124:32;7121:52;;;7169:1;7166;7159:12;7121:52;7209:9;7196:23;7238:18;7279:2;7271:6;7268:14;7265:34;;;7295:1;7292;7285:12;7265:34;7333:6;7322:9;7318:22;7308:32;;7378:7;7371:4;7367:2;7363:13;7359:27;7349:55;;7400:1;7397;7390:12;7349:55;7440:2;7427:16;7466:2;7458:6;7455:14;7452:34;;;7482:1;7479;7472:12;7452:34;7529:7;7522:4;7513:6;7509:2;7505:15;7501:26;7498:39;7495:59;;;7550:1;7547;7540:12;7495:59;7581:4;7573:13;;;;7605:6;;-1:-1:-1;7643:20:1;;;;7630:34;;7004:666;-1:-1:-1;;;;7004:666:1:o;7675:186::-;7734:6;7787:2;7775:9;7766:7;7762:23;7758:32;7755:52;;;7803:1;7800;7793:12;7755:52;7826:29;7845:9;7826:29;:::i;8119:367::-;8182:8;8192:6;8246:3;8239:4;8231:6;8227:17;8223:27;8213:55;;8264:1;8261;8254:12;8213:55;-1:-1:-1;8287:20:1;;8330:18;8319:30;;8316:50;;;8362:1;8359;8352:12;8316:50;8399:4;8391:6;8387:17;8375:29;;8459:3;8452:4;8442:6;8439:1;8435:14;8427:6;8423:27;8419:38;8416:47;8413:67;;;8476:1;8473;8466:12;8491:770;8610:6;8618;8626;8634;8687:2;8675:9;8666:7;8662:23;8658:32;8655:52;;;8703:1;8700;8693:12;8655:52;8743:9;8730:23;8772:18;8813:2;8805:6;8802:14;8799:34;;;8829:1;8826;8819:12;8799:34;8868:70;8930:7;8921:6;8910:9;8906:22;8868:70;:::i;:::-;8957:8;;-1:-1:-1;8842:96:1;-1:-1:-1;9045:2:1;9030:18;;9017:32;;-1:-1:-1;9061:16:1;;;9058:36;;;9090:1;9087;9080:12;9058:36;;9129:72;9193:7;9182:8;9171:9;9167:24;9129:72;:::i;:::-;8491:770;;;;-1:-1:-1;9220:8:1;-1:-1:-1;;;;8491:770:1:o;9266:361::-;9354:6;9407:2;9395:9;9386:7;9382:23;9378:32;9375:52;;;9423:1;9420;9413:12;9375:52;9463:9;9450:23;9496:18;9488:6;9485:30;9482:50;;;9528:1;9525;9518:12;9482:50;9551:70;9613:7;9604:6;9593:9;9589:22;9551:70;:::i;10410:248::-;10478:6;10486;10539:2;10527:9;10518:7;10514:23;10510:32;10507:52;;;10555:1;10552;10545:12;10507:52;-1:-1:-1;;10578:23:1;;;10648:2;10633:18;;;10620:32;;-1:-1:-1;10410:248:1:o;10663:898::-;10853:4;10882:2;10922;10911:9;10907:18;10952:2;10941:9;10934:21;10975:6;11010;11004:13;11041:6;11033;11026:22;11079:2;11068:9;11064:18;11057:25;;11141:2;11131:6;11128:1;11124:14;11113:9;11109:30;11105:39;11091:53;;11179:2;11171:6;11167:15;11200:1;11210:322;11224:6;11221:1;11218:13;11210:322;;;11313:66;11301:9;11293:6;11289:22;11285:95;11280:3;11273:108;11404:48;11445:6;11436;11430:13;11404:48;:::i;:::-;11394:58;-1:-1:-1;11510:12:1;;;;11475:15;;;;11246:1;11239:9;11210:322;;;-1:-1:-1;11549:6:1;;10663:898;-1:-1:-1;;;;;;;10663:898:1:o;11566:693::-;11677:6;11685;11693;11701;11709;11717;11725;11778:3;11766:9;11757:7;11753:23;11749:33;11746:53;;;11795:1;11792;11785:12;11746:53;11818:29;11837:9;11818:29;:::i;:::-;11808:39;;11866:38;11900:2;11889:9;11885:18;11866:38;:::i;:::-;11856:48;;11951:2;11940:9;11936:18;11923:32;11913:42;;12002:2;11991:9;11987:18;11974:32;11964:42;;12056:3;12045:9;12041:19;12028:33;12101:4;12094:5;12090:16;12083:5;12080:27;12070:55;;12121:1;12118;12111:12;12070:55;11566:693;;;;-1:-1:-1;11566:693:1;;;;12144:5;12196:3;12181:19;;12168:33;;-1:-1:-1;12248:3:1;12233:19;;;12220:33;;11566:693;-1:-1:-1;;11566:693:1:o;12264:260::-;12332:6;12340;12393:2;12381:9;12372:7;12368:23;12364:32;12361:52;;;12409:1;12406;12399:12;12361:52;12432:29;12451:9;12432:29;:::i;:::-;12422:39;;12480:38;12514:2;12503:9;12499:18;12480:38;:::i;:::-;12470:48;;12264:260;;;;;:::o;12529:505::-;12624:6;12632;12640;12693:2;12681:9;12672:7;12668:23;12664:32;12661:52;;;12709:1;12706;12699:12;12661:52;12745:9;12732:23;12722:33;;12806:2;12795:9;12791:18;12778:32;12833:18;12825:6;12822:30;12819:50;;;12865:1;12862;12855:12;12819:50;12904:70;12966:7;12957:6;12946:9;12942:22;12904:70;:::i;:::-;12529:505;;12993:8;;-1:-1:-1;12878:96:1;;-1:-1:-1;;;;12529:505:1:o;13039:437::-;13118:1;13114:12;;;;13161;;;13182:61;;13236:4;13228:6;13224:17;13214:27;;13182:61;13289:2;13281:6;13278:14;13258:18;13255:38;13252:218;;13326:77;13323:1;13316:88;13427:4;13424:1;13417:15;13455:4;13452:1;13445:15;13610:783;13663:3;13704:5;13698:12;13733:36;13759:9;13733:36;:::i;:::-;13788:1;13805:18;;;13832:191;;;;14037:1;14032:355;;;;13798:589;;13832:191;13880:66;13869:9;13865:82;13860:3;13853:95;14003:6;13996:14;13989:22;13981:6;13977:35;13972:3;13968:45;13961:52;;13832:191;;14032:355;14063:5;14060:1;14053:16;14092:4;14137:2;14134:1;14124:16;14162:1;14176:165;14190:6;14187:1;14184:13;14176:165;;;14268:14;;14255:11;;;14248:35;14311:16;;;;14205:10;;14176:165;;;14180:3;;;14370:6;14365:3;14361:16;14354:23;;13798:589;;;;;13610:783;;;;:::o;14398:202::-;14528:3;14553:41;14590:3;14582:6;14553:41;:::i;15122:184::-;15174:77;15171:1;15164:88;15271:4;15268:1;15261:15;15295:4;15292:1;15285:15;15311:1021;15420:4;15449:2;15478;15467:9;15460:21;15501:1;15534:6;15528:13;15564:36;15590:9;15564:36;:::i;:::-;15636:6;15631:2;15620:9;15616:18;15609:34;15662:2;15683:1;15715:2;15704:9;15700:18;15732:1;15727:216;;;;15957:1;15952:354;;;;15693:613;;15727:216;15790:66;15779:9;15775:82;15770:2;15759:9;15755:18;15748:110;15930:2;15918:6;15911:14;15904:22;15901:1;15897:30;15886:9;15882:46;15878:55;15871:62;;15727:216;;15952:354;15983:6;15980:1;15973:17;16031:2;16028:1;16018:16;16056:1;16070:180;16084:6;16081:1;16078:13;16070:180;;;16177:14;;16153:17;;;16149:26;;16142:50;16220:16;;;;16099:10;;16070:180;;;16274:17;;16270:26;;;-1:-1:-1;;15693:613:1;-1:-1:-1;16323:3:1;;15311:1021;-1:-1:-1;;;;;;;;15311:1021:1:o;16337:392::-;16513:3;16541:41;16578:3;16570:6;16541:41;:::i;:::-;16611:6;16605:13;16627:65;16685:6;16681:2;16674:4;16666:6;16662:17;16627:65;:::i;:::-;16708:15;;16337:392;-1:-1:-1;;;;16337:392:1:o;16734:184::-;16786:77;16783:1;16776:88;16883:4;16880:1;16873:15;16907:4;16904:1;16897:15;16923:128;16990:9;;;17011:11;;;17008:37;;;17025:18;;:::i;17056:195::-;17095:3;17126:66;17119:5;17116:77;17113:103;;17196:18;;:::i;:::-;-1:-1:-1;17243:1:1;17232:13;;17056:195::o;17256:125::-;17321:9;;;17342:10;;;17339:36;;;17355:18;;:::i;17386:604::-;17479:4;17485:6;17545:11;17532:25;17635:66;17624:8;17608:14;17604:29;17600:102;17580:18;17576:127;17566:155;;17717:1;17714;17707:12;17566:155;17744:33;;17796:20;;;-1:-1:-1;17839:18:1;17828:30;;17825:50;;;17871:1;17868;17861:12;17825:50;17904:4;17892:17;;-1:-1:-1;17955:1:1;17951:14;;;17935;17931:35;17921:46;;17918:66;;;17980:1;17977;17970:12;17995:168;18068:9;;;18099;;18116:15;;;18110:22;;18096:37;18086:71;;18137:18;;:::i;18777:184::-;18829:77;18826:1;18819:88;18926:4;18923:1;18916:15;18950:4;18947:1;18940:15;18966:184;19018:77;19015:1;19008:88;19115:4;19112:1;19105:15;19139:4;19136:1;19129:15;19155:545;19257:2;19252:3;19249:11;19246:448;;;19293:1;19318:5;19314:2;19307:17;19363:4;19359:2;19349:19;19433:2;19421:10;19417:19;19414:1;19410:27;19404:4;19400:38;19469:4;19457:10;19454:20;19451:47;;;-1:-1:-1;19492:4:1;19451:47;19547:2;19542:3;19538:12;19535:1;19531:20;19525:4;19521:31;19511:41;;19602:82;19620:2;19613:5;19610:13;19602:82;;;19665:17;;;19646:1;19635:13;19602:82;;19936:1328;20060:18;20055:3;20052:27;20049:53;;;20082:18;;:::i;:::-;20111:94;20201:3;20161:38;20193:4;20187:11;20161:38;:::i;:::-;20155:4;20111:94;:::i;:::-;20231:1;20256:2;20251:3;20248:11;20273:1;20268:738;;;;21050:1;21067:3;21064:93;;;-1:-1:-1;21123:19:1;;;21110:33;21064:93;19842:66;19833:1;19829:11;;;19825:84;19821:89;19811:100;19917:1;19913:11;;;19808:117;21170:78;;20241:1017;;20268:738;13557:1;13550:14;;;13594:4;13581:18;;20313:66;20304:76;;;20467:9;20489:229;20503:7;20500:1;20497:14;20489:229;;;20592:19;;;20579:33;20564:49;;20699:4;20684:20;;;;20652:1;20640:14;;;;20519:12;20489:229;;;20493:3;20746;20737:7;20734:16;20731:219;;;20866:66;20860:3;20854;20851:1;20847:11;20843:21;20839:94;20835:99;20822:9;20817:3;20813:19;20800:33;20796:139;20788:6;20781:155;20731:219;;;20993:1;20987:3;20984:1;20980:11;20976:19;20970:4;20963:33;20241:1017;;;19936:1328;;;:::o;21269:326::-;21358:6;21353:3;21346:19;21410:6;21403:5;21396:4;21391:3;21387:14;21374:43;;21462:1;21455:4;21446:6;21441:3;21437:16;21433:27;21426:38;21328:3;21584:4;21514:66;21509:2;21501:6;21497:15;21493:88;21488:3;21484:98;21480:109;21473:116;;21269:326;;;;:::o;21600:579::-;21670:5;21677:6;21737:3;21724:17;21819:66;21808:8;21792:14;21788:29;21784:102;21764:18;21760:127;21750:155;;21901:1;21898;21891:12;21750:155;21929:33;;22033:4;22020:18;;;-1:-1:-1;21981:21:1;;-1:-1:-1;22061:18:1;22050:30;;22047:50;;;22093:1;22090;22083:12;22047:50;22147:6;22144:1;22140:14;22124;22120:35;22113:5;22109:47;22106:67;;;22169:1;22166;22159:12;22184:470;22284:6;22279:3;22272:19;22254:3;22310:4;22339:2;22334:3;22330:12;22323:19;;22365:5;22388:1;22398:231;22412:6;22409:1;22406:13;22398:231;;;22505:42;22477:26;22496:6;22477:26;:::i;:::-;22473:75;22461:88;;22569:12;;;;22604:15;;;;22434:1;22427:9;22398:231;;;-1:-1:-1;22645:3:1;;22184:470;-1:-1:-1;;;;;22184:470:1:o;22659:358::-;22759:6;22754:3;22747:19;22729:3;22789:66;22781:6;22778:78;22775:98;;;22869:1;22866;22859:12;22775:98;22905:6;22902:1;22898:14;22957:8;22950:5;22943:4;22938:3;22934:14;22921:45;22986:18;;;;23006:4;22982:29;;22659:358;-1:-1:-1;;;22659:358:1:o;23022:1661::-;23198:4;23227:42;23308:2;23300:6;23296:15;23285:9;23278:34;23348:2;23343;23332:9;23328:18;23321:30;23419:2;23391:26;23410:6;23391:26;:::i;:::-;23387:35;23382:2;23371:9;23367:18;23360:63;;23483:2;23475:6;23471:15;23458:29;23563:66;23554:6;23538:14;23534:27;23530:100;23510:18;23506:125;23496:153;;23645:1;23642;23635:12;23496:153;23671:31;;23779:2;23768:14;;;23725:19;23805:18;23794:30;;23791:50;;;23837:1;23834;23827:12;23791:50;23886:6;23870:14;23866:27;23857:7;23853:41;23850:61;;;23907:1;23904;23897:12;23850:61;23947:4;23942:2;23931:9;23927:18;23920:32;23975:64;24034:3;24023:9;24019:19;24011:6;24002:7;23975:64;:::i;:::-;23961:78;;;24082:67;24145:2;24137:6;24133:15;24125:6;24082:67;:::i;:::-;24168:66;24300:2;24288:9;24280:6;24276:22;24272:31;24265:4;24254:9;24250:20;24243:61;24327:73;24393:6;24379:12;24365;24327:73;:::i;:::-;24313:87;;24447:67;24510:2;24502:6;24498:15;24490:6;24447:67;:::i;:::-;24409:105;;;;24579:2;24567:9;24559:6;24555:22;24551:31;24545:3;24534:9;24530:19;24523:60;;24600:77;24670:6;24654:14;24638;24600:77;:::i;:::-;24592:85;23022:1661;-1:-1:-1;;;;;;;23022:1661:1:o;24688:581::-;24766:4;24772:6;24832:11;24819:25;24922:66;24911:8;24895:14;24891:29;24887:102;24867:18;24863:127;24853:155;;25004:1;25001;24994:12;24853:155;25031:33;;25083:20;;;-1:-1:-1;25126:18:1;25115:30;;25112:50;;;25158:1;25155;25148:12;25112:50;25191:4;25179:17;;-1:-1:-1;25222:14:1;25218:27;;;25208:38;;25205:58;;;25259:1;25256;25249:12;25274:273;25459:6;25451;25446:3;25433:33;25415:3;25485:16;;25510:13;;;25485:16;25274:273;-1:-1:-1;25274:273:1:o;25552:184::-;25604:77;25601:1;25594:88;25701:4;25698:1;25691:15;25725:4;25722:1;25715:15;25741:120;25781:1;25807;25797:35;;25812:18;;:::i;:::-;-1:-1:-1;25846:9:1;;25741:120::o;25866:184::-;25936:6;25989:2;25977:9;25968:7;25964:23;25960:32;25957:52;;;26005:1;26002;25995:12;25957:52;-1:-1:-1;26028:16:1;;25866:184;-1:-1:-1;25866:184:1:o;26357:245::-;26424:6;26477:2;26465:9;26456:7;26452:23;26448:32;26445:52;;;26493:1;26490;26483:12;26445:52;26525:9;26519:16;26544:28;26566:5;26544:28;:::i;28078:372::-;28254:3;28292:6;28286:13;28308:66;28367:6;28362:3;28355:4;28347:6;28343:17;28308:66;:::i;:::-;28390:54;28436:6;28431:3;28427:16;28419:6;28390:54;:::i;28455:475::-;28676:3;28704:41;28741:3;28733:6;28704:41;:::i;:::-;28774:6;28768:13;28790:65;28848:6;28844:2;28837:4;28829:6;28825:17;28790:65;:::i;:::-;28871:53;28916:6;28912:2;28908:15;28900:6;28871:53;:::i;29384:112::-;29416:1;29442;29432:35;;29447:18;;:::i;:::-;-1:-1:-1;29481:9:1;;29384:112::o;30520:196::-;30559:3;30587:5;30577:39;;30596:18;;:::i;:::-;-1:-1:-1;30643:66:1;30632:78;;30520:196::o;30721:642::-;30991:3;31029:6;31023:13;31045:66;31104:6;31099:3;31092:4;31084:6;31080:17;31045:66;:::i;:::-;31172:13;31133:16;;;31158:28;;;31211:13;;31233:79;31211:13;31298:2;31287:14;;31280:4;31268:17;;31233:79;:::i;:::-;31332:20;31354:2;31328:29;;30721:642;-1:-1:-1;;;;30721:642:1:o;31368:1283::-;31988:18;31983:3;31976:31;31958:3;32036:6;32030:13;32052:75;32120:6;32115:2;32110:3;32106:12;32099:4;32091:6;32087:17;32052:75;:::i;:::-;32191:19;32186:2;32146:16;;;32178:11;;;32171:40;32236:13;;32258:76;32236:13;32320:2;32312:11;;32305:4;32293:17;;32258:76;:::i;:::-;32399:11;32394:2;32353:17;;;;32386:11;;;32379:32;32436:13;;32458:76;32436:13;32520:2;32512:11;;32505:4;32493:17;;32458:76;:::i;:::-;32599:18;32594:2;32553:17;;;;32586:11;;;32579:39;32642:2;32634:11;;31368:1283;-1:-1:-1;;;;;31368:1283:1:o;32656:1474::-;32782:3;32776:10;32809:18;32801:6;32798:30;32795:56;;;32831:18;;:::i;:::-;32860:97;32950:6;32910:38;32942:4;32936:11;32910:38;:::i;:::-;32904:4;32860:97;:::i;:::-;33012:4;;33076:2;33065:14;;33093:1;33088:785;;;;33917:1;33934:6;33931:89;;;-1:-1:-1;33986:19:1;;;33980:26;33931:89;19842:66;19833:1;19829:11;;;19825:84;19821:89;19811:100;19917:1;19913:11;;;19808:117;34033:81;;33058:1066;;33088:785;13557:1;13550:14;;;13594:4;13581:18;;33136:66;33124:79;;;33304:236;33318:7;33315:1;33312:14;33304:236;;;33407:19;;;33401:26;33386:42;;33499:27;;;;33467:1;33455:14;;;;33334:19;;33304:236;;;33308:3;33568:6;33559:7;33556:19;33553:261;;;33629:19;;;33623:26;33730:66;33712:1;33708:14;;;33724:3;33704:24;33700:97;33696:102;33681:118;33666:134;;33553:261;-1:-1:-1;;;;;33860:1:1;33844:14;;;33840:22;33827:36;;-1:-1:-1;32656:1474:1:o;34135:175::-;34172:3;34216:4;34209:5;34205:16;34245:4;34236:7;34233:17;34230:43;;34253:18;;:::i;:::-;34302:1;34289:15;;34135:175;-1:-1:-1;;34135:175:1:o;34315:227::-;34383:64;34467:10;;;34479;;;34463:27;;34502:11;;;34499:37;;;34516:18;;:::i;34547:496::-;34726:3;34764:6;34758:13;34780:66;34839:6;34834:3;34827:4;34819:6;34815:17;34780:66;:::i;:::-;34909:13;;34868:16;;;;34931:70;34909:13;34868:16;34978:4;34966:17;;34931:70;:::i;35048:703::-;35275:3;35313:6;35307:13;35329:66;35388:6;35383:3;35376:4;35368:6;35364:17;35329:66;:::i;:::-;35458:13;;35417:16;;;;35480:70;35458:13;35417:16;35527:4;35515:17;;35480:70;:::i;:::-;35617:13;;35572:20;;;35639:70;35617:13;35572:20;35686:4;35674:17;;35639:70;:::i;:::-;35725:20;;35048:703;-1:-1:-1;;;;;35048:703:1:o

Swarm Source

ipfs://bf164ab27a6e986c8b955d0a65d80a4c4301fb9e3dbb0237ce75331b01fed532
Loading