BNB Price: $615.47 (+3.06%)
 

Overview

Max Total Supply

199,999,355,888.557022MSVP

Holders

1,007,437 (0.00%)

Market

Price

$0.0223 @ 0.000036 BNB (+1.29%)

Onchain Market Cap

-

Circulating Supply Market Cap

$0.00

Other Info

Token Contract (WITH 18 Decimals)

Balance
1.727356642295831635 MSVP

Value
$0.04 ( ~6.49910564512056E-05 BNB) [0.0000%]
0x34fe52150257db0ce80a8dc52cedb28dfa0c4020
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

MetaSoilVerse Protocol (MSVP) is a blockchain-based infrastructure layer developed to facilitate the tokenization and yield generation of Real-World Assets (RWAs).

Market

Volume (24H):$97,706.00
Market Capitalization:$0.00
Circulating Supply:0.00 MSVP
Market Data Source: Coinmarketcap


Update? Click here to update the token ICO / general information

Contract Source Code Verified (Exact Match)

Contract Name:
MSVP

Compiler Version
v0.8.30+commit.73712a01

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
/**
 *Submitted for verification at BscScan.com on 2025-12-23
*/

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity 0.8.30;

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}





            

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity 0.8.30;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}





            

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity 0.8.30;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity 0.8.30;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}





            

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity 0.8.30;

////import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity 0.8.30;

////import "./math/Math.sol";
////import "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}





            

// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity 0.8.30;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity 0.8.30;

////import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity 0.8.30;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

    /**
     * @dev Moves `amount` tokens from `from` to `to` 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, uint256 amount) external returns (bool);
}





            

// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity 0.8.30;

////import "../IERC20.sol";

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

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

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





            

// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity 0.8.30;

////import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity 0.8.30;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)

pragma solidity 0.8.30;

////import "./IAccessControl.sol";
////import "../utils/Context.sol";
////import "../utils/Strings.sol";
////import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(account),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * May emit a {RoleGranted} event.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)

pragma solidity 0.8.30;

////import "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
        _transferOwnership(sender);
    }
}





            

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)

pragma solidity 0.8.30;

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

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

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

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

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

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

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

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

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

        _afterTokenTransfer(account, address(0), amount);
    }

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

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

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

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

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





pragma solidity 0.8.30;

/**
 * @title MSVTokenVesting
 * @dev MetaSoilVerse Token with integrated vesting functionality based on precise tokenomics schedule
 * Locked tokens are visible in balance but non-transferable
 */
contract MSVP is ERC20, Ownable2Step, ReentrancyGuard, Pausable, AccessControl {
    // Token configuration
    uint256 public constant TOTAL_SUPPLY = 200_000_000_000 * 10 ** 18; // 200 billion tokens
    uint256 public constant AIRDROP_SUPPLY = 72_000_000_000 * 10 ** 18; // 72 billion tokens for airdrop
    uint256 public constant MAX_TAX_RATE = 100; // Maximum 10% tax
    uint256 public constant TAX_DENOMINATOR = 1000; // Tax precision (0.1%)

    // Transfer tax configuration
    uint256 public transferTaxRate = 50; // 5% transfer tax
    uint256 public lpContributionRate = 20; // 2% to LP
    uint256 public developmentRate = 15; // 1.5% development fee
    uint256 public marketingRate = 10; // 1% marketing
    uint256 public burnRate = 5; // 0.5% burn

    // Addresses
    address public lpWallet;
    address public marketingWallet;
    address public developmentWallet;
    address public treasuryWallet; // receives residual tax when burnRate is zero

    // Excluded addresses from tax
    mapping(address => bool) public isExcludedFromTax;
    mapping(address => bool) public isExcludedFromMaxTx;

    // Max transaction limit
    uint256 public maxTxAmount = TOTAL_SUPPLY / 100; // 1% of total supply

    // Role-based access control
    bytes32 public constant SUBADMIN_ROLE = keccak256('SUBADMIN_ROLE');

    // Vesting configuration based on tokenomics schedule
    uint256 public constant CLIFF_DURATION = 180 days; // 6 months cliff
    uint256 public constant FIRST_YEAR_UNLOCK_PERCENTAGE = 12; // 1.2% (12/1000)
    uint256 public constant POST_Q5_UNLOCK_PERCENTAGE = 70; // 7% (70/1000)
    uint256 public constant FINAL_UNLOCK_PERCENTAGE = 60; // 6% (60/1000)

    // Vesting schedule per user
    struct VestingSchedule {
        uint256 totalAmount; // Total tokens allocated for vesting
        uint256 unlockedAmount; // Amount already unlocked
        uint256 startTime; // Vesting start time (TGE)
        uint256 endTime; // Vesting end time
        bool isActive; // Whether vesting is active
        bool isAirdrop; // Whether this is from airdrop
        address creator; // Address that created this schedule and can modify it
        bool isCancelled; // Whether this schedule was permanently cancelled
    }

    // Mapping from user address to vesting schedule (latest at creation; kept for backward compatibility only)
    mapping(address => VestingSchedule) public vestingSchedules;
    // Mapping from user address to all vesting schedules (supports multiple schedules per user)
    mapping(address => VestingSchedule[]) public userVestingSchedules;

    // Arrays to track all participants
    address[] public participants;
    mapping(address => bool) public isParticipant;

    // Admin controls
    uint256 public totalAllocated = 0;
    uint256 public totalUnlocked = 0;

    // Events
    event TransferTaxUpdated(uint256 newTaxRate);
    event LPContributionRateUpdated(uint256 newRate);
    event DevelopmentRateUpdated(uint256 newRate);
    event MarketingRateUpdated(uint256 newRate);
    event BurnRateUpdated(uint256 newRate);
    event LPWalletUpdated(address newWallet);
    event MarketingWalletUpdated(address newWallet);
    event DevelopmentWalletUpdated(address newWallet);
    event TreasuryWalletUpdated(address newWallet);
    event MaxTxAmountUpdated(uint256 newAmount);
    event TaxExclusionUpdated(address account, bool excluded);
    event MaxTxExclusionUpdated(address account, bool excluded);

    // Vesting events
    event VestingScheduleCreated(address indexed user, uint256 amount, uint256 startTime, uint256 endTime);
    event TokensUnlocked(address indexed user, uint256 amount, uint256 timestamp);
    event VestingScheduleModified(address indexed user, uint256 newAmount, uint256 timestamp);
    event EarlyRelease(address indexed user, uint256 amount, uint256 timestamp);
    event EmergencyUnlockAll(address indexed user, uint256 amount, uint256 timestamp);
    event VestingScheduleDeactivated(address indexed user, uint256 timestamp);
    event VestingScheduleReactivated(address indexed user, uint256 timestamp);
    event VestingScheduleCancelled(address indexed user, uint256 lockedAmount, uint256 timestamp);
    event AirdropStatusToggled(address indexed user, bool isAirdrop, uint256 timestamp);
    event VestingScheduleCompleted(address indexed user, uint256 totalAmount, uint256 timestamp);
    event VestingInconsistencyDetected(
        address indexed user,
        uint256 recordedAmount,
        uint256 calculatedAmount,
        uint256 timestamp
    );
    event TokensTransferredForVesting(address indexed user, uint256 amount, uint256 timestamp);

    // Role management events
    event SubadminAdded(address indexed subadmin, address indexed by);
    event SubadminRemoved(address indexed subadmin, address indexed by);

    constructor(
        address _lpWallet,
        address _marketingWallet,
        address _developmentWallet
    ) ERC20('MetaSoilVerseProtocol', 'MSVP') {
        require(_lpWallet != address(0), 'Invalid LP wallet');
        require(_marketingWallet != address(0), 'Invalid marketing wallet');
        require(_developmentWallet != address(0), 'Invalid development wallet');

        lpWallet = _lpWallet;
        marketingWallet = _marketingWallet;
        developmentWallet = _developmentWallet;
        treasuryWallet = _developmentWallet; // default treasury to development wallet

        // Exclude owner and contract from tax
        isExcludedFromTax[msg.sender] = true;
        isExcludedFromTax[address(this)] = true;

        // Exclude owner and contract from max transaction limit
        isExcludedFromMaxTx[msg.sender] = true;
        isExcludedFromMaxTx[address(this)] = true;

        // Mint total supply to owner
        _mint(msg.sender, TOTAL_SUPPLY);

        // Set up initial roles
        _grantRole(SUBADMIN_ROLE, msg.sender);
    }

    // Role Management Functions

    /**
     * @dev Grant subadmin role to an address (only callable by owner)
     */
    function grantSubadminRole(address account) external onlyOwner {
        require(account != address(0), 'Invalid address');
        _grantRole(SUBADMIN_ROLE, account);
        // Exclude subadmin from transfer tax to avoid vesting allocation mismatches
        isExcludedFromTax[account] = true;
        emit SubadminAdded(account, msg.sender);
    }

    /**
     * @dev Revoke subadmin role from an address (only callable by owner)
     */
    function revokeSubadminRole(address account) external onlyOwner {
        require(account != address(0), 'Invalid address');
        _revokeRole(SUBADMIN_ROLE, account);
        // Remove tax exclusion when subadmin role is revoked
        isExcludedFromTax[account] = false;
        emit SubadminRemoved(account, msg.sender);
    }

    /**
     * @dev Update treasury wallet (receiver of residual tax when burn is disabled)
     */
    function updateTreasuryWallet(address newWallet) external onlyOwner {
        require(newWallet != address(0), 'Invalid wallet address');
        treasuryWallet = newWallet;
        emit TreasuryWalletUpdated(newWallet);
    }

    /**
     * @dev Check if address has subadmin role
     */
    function hasSubadminRole(address account) external view returns (bool) {
        return hasRole(SUBADMIN_ROLE, account);
    }

    /**
     * @dev Override balanceOf to show actual token balance
     * This shows the real tokens held in the wallet (including received tokens)
     */
    function balanceOf(address account) public view override returns (uint256) {
        // Always show actual tokens in wallet
        return super.balanceOf(account);
    }

    /**
     * @dev Get vesting allocation (total tokens allocated for vesting)
     * This shows the vesting schedule amount, not the actual balance
     */
    function getVestingAllocation(address account) external view returns (uint256) {
        if (!isParticipant[account]) {
            return 0;
        }
        VestingSchedule[] storage schedules = userVestingSchedules[account];
        uint256 total = 0;
        for (uint256 i = 0; i < schedules.length; i++) {
            if (schedules[i].isActive) {
                total += schedules[i].totalAmount;
            }
        }
        return total;
    }

    /**
     * @dev Get transferable balance (unlocked tokens for vesting participants)
     * For vesting participants: returns unlocked vesting tokens + any other unlocked tokens
     * For non-participants: returns full balance
     */
    function transferableBalance(address account) public view returns (uint256) {
        if (isParticipant[account]) {
            // For vesting participants: unlocked vesting tokens + any other unlocked tokens
            uint256 totalBalance = super.balanceOf(account);
            uint256 lockedAmount = getLockedAmount(account);

            // The correct calculation: total balance - locked amount
            // This automatically includes unlocked vesting + any other tokens
            return totalBalance - lockedAmount;
        } else {
            // For non-participants, full balance is transferable
            return super.balanceOf(account);
        }
    }

    /**
     * @dev Override transfer to include vesting logic and tax
     */
    function _transfer(address from, address to, uint256 amount) internal virtual override whenNotPaused {
        require(from != address(0), 'ERC20: transfer from the zero address');
        require(to != address(0), 'ERC20: transfer to the zero address');
        require(amount > 0, 'Transfer amount must be greater than zero');

        // Update unlocked amounts for both addresses if they are participants
        if (isParticipant[from]) {
            updateUnlockedAmountsForUser(from);
        }
        if (isParticipant[to]) {
            updateUnlockedAmountsForUser(to);
        }

        // Check transferable balance
        uint256 transferable = transferableBalance(from);
        require(transferable >= amount, 'Insufficient transferable balance');

        // Check max transaction limit (unless excluded)
        if (!isExcludedFromMaxTx[from] && !isExcludedFromMaxTx[to]) {
            require(amount <= maxTxAmount, 'Transfer amount exceeds max transaction limit');
        }

        // Calculate tax
        uint256 taxAmount = 0;
        if (transferTaxRate > 0 && !isExcludedFromTax[from] && !isExcludedFromTax[to]) {
            taxAmount = (amount * transferTaxRate) / TAX_DENOMINATOR;
        }

        uint256 transferAmount = amount - taxAmount;

        // Transfer tokens to recipient (amount minus tax)
        super._transfer(from, to, transferAmount);

        // Transfer tax to contract if applicable
        if (taxAmount > 0) {
            super._transfer(from, address(this), taxAmount);
            _distributeTaxes(taxAmount);
        }
    }

    /**
     * @dev Distribute transfer taxes to different wallets
     */
    function _distributeTaxes(uint256 taxAmount) internal {
        // Only distribute if tax amount is greater than 0
        if (taxAmount == 0) {
            return;
        }

        uint256 remainingTax = taxAmount;

        // LP contribution
        if (lpContributionRate > 0) {
            uint256 lpAmount = (taxAmount * lpContributionRate) / transferTaxRate;
            if (lpAmount > 0) {
                super._transfer(address(this), lpWallet, lpAmount);
                remainingTax -= lpAmount;
            }
        }

        // Development fee
        if (developmentRate > 0) {
            uint256 developmentAmount = (taxAmount * developmentRate) / transferTaxRate;
            if (developmentAmount > 0) {
                super._transfer(address(this), developmentWallet, developmentAmount);
                remainingTax -= developmentAmount;
            }
        }

        // Marketing
        if (marketingRate > 0) {
            uint256 marketingAmount = (taxAmount * marketingRate) / transferTaxRate;
            if (marketingAmount > 0) {
                super._transfer(address(this), marketingWallet, marketingAmount);
                remainingTax -= marketingAmount;
            }
        }

        // Handle remaining tax
        if (remainingTax > 0) {
            if (burnRate > 0) {
                _burn(address(this), remainingTax);
            } else {
                // Redirect residual tax when burn is disabled
                super._transfer(address(this), treasuryWallet, remainingTax);
            }
        }
    }

    // Vesting Functions
    // The contract supports multiple vesting schedules per user.
    // All admin actions target a specific schedule via its index in `userVestingSchedules[user]`.
    // The compatibility mapping `vestingSchedules[user]` is set on creation only and is not mutated afterwards.

    /**
     * @notice Create a vesting schedule for a single user.
     * @dev Tokens are first transferred (with tax if applicable), then the post-tax credited amount
     *      is used as the schedule's totalAmount to ensure allocations match the actual received balance.
     *      The schedule is appended to `userVestingSchedules[user]` and the compatibility mapping is updated once.
     * @param user Recipient of the vesting schedule
     * @param amount Gross amount to transfer to the user (pre-tax)
     */
    function createVestingSchedule(address user, uint256 amount) external onlyRole(SUBADMIN_ROLE) nonReentrant {
        require(user != address(0), 'Invalid user address');
        require(amount > 0, 'Amount must be greater than zero');

        require(balanceOf(msg.sender) >= amount, 'Insufficient tokens for vesting');
        // Perform transfer which may apply tax
        _transfer(msg.sender, user, amount);

        // Determine actually credited (post-tax) amount to ensure schedule matches real balance
        bool taxApplies = (transferTaxRate > 0 && !isExcludedFromTax[msg.sender] && !isExcludedFromTax[user]);
        uint256 creditedAmount = taxApplies ? (amount - ((amount * transferTaxRate) / TAX_DENOMINATOR)) : amount;

        // Emit event with credited amount used for vesting
        emit TokensTransferredForVesting(user, creditedAmount, block.timestamp);

        uint256 startTime = block.timestamp;
        uint256 endTime = startTime + (61 * 30 days); // 61 months total vesting period

        VestingSchedule memory newSchedule = VestingSchedule({
            totalAmount: creditedAmount,
            unlockedAmount: 0,
            startTime: startTime,
            endTime: endTime,
            isActive: true,
            isAirdrop: true,
            creator: msg.sender,
            isCancelled: false
        });

        // Store as the latest schedule (backward compatibility)
        vestingSchedules[user] = newSchedule;
        // Append to user's schedules (support multiple)
        userVestingSchedules[user].push(newSchedule);

        if (!isParticipant[user]) {
            participants.push(user);
            isParticipant[user] = true;
        }

        totalAllocated += creditedAmount;

        emit VestingScheduleCreated(user, creditedAmount, startTime, endTime);
    }

    /**
     * @notice Create multiple vesting schedules.
     * @dev Mirrors `createVestingSchedule` but for arrays; each entry uses the post-tax credited amount
     *      for the schedule's totalAmount. Invalid entries (zero address or zero amount) are skipped.
     */
    function createVestingSchedules(
        address[] calldata users,
        uint256[] calldata amounts
    ) external onlyRole(SUBADMIN_ROLE) nonReentrant {
        require(users.length == amounts.length, 'Arrays length mismatch');
        require(users.length > 0, 'Empty arrays');

        uint256 totalTokensNeeded = 0;
        for (uint256 i = 0; i < amounts.length; i++) {
            if (users[i] != address(0) && amounts[i] > 0) {
                totalTokensNeeded += amounts[i];
            }
        }
        require(balanceOf(msg.sender) >= totalTokensNeeded, 'Insufficient tokens for bulk vesting');

        uint256 startTime = block.timestamp;
        uint256 endTime = startTime + (61 * 30 days); // 61 months total vesting period

        for (uint256 i = 0; i < users.length; i++) {
            if (users[i] != address(0) && amounts[i] > 0) {
                _transfer(msg.sender, users[i], amounts[i]);
                // Compute credited (post-tax) amount for vesting allocation
                bool taxApplies = (transferTaxRate > 0 &&
                    !isExcludedFromTax[msg.sender] &&
                    !isExcludedFromTax[users[i]]);
                uint256 creditedAmount = taxApplies
                    ? (amounts[i] - ((amounts[i] * transferTaxRate) / TAX_DENOMINATOR))
                    : amounts[i];
                emit TokensTransferredForVesting(users[i], creditedAmount, block.timestamp);

                VestingSchedule memory newSchedule = VestingSchedule({
                    totalAmount: creditedAmount,
                    unlockedAmount: 0,
                    startTime: startTime,
                    endTime: endTime,
                    isActive: true,
                    isAirdrop: true,
                    creator: msg.sender,
                    isCancelled: false
                });

                // Store as the latest schedule (backward compatibility)
                vestingSchedules[users[i]] = newSchedule;
                // Append to user's schedules (support multiple)
                userVestingSchedules[users[i]].push(newSchedule);

                if (!isParticipant[users[i]]) {
                    participants.push(users[i]);
                    isParticipant[users[i]] = true;
                }

                totalAllocated += creditedAmount;

                emit VestingScheduleCreated(users[i], creditedAmount, startTime, endTime);
            }
        }
    }

    /**
     * @dev Internal helper to get the index of the latest schedule for a user.
     * @return has Whether at least one schedule exists
     * @return idx Index of the last schedule when it exists
     */
    function _latestScheduleIndex(address user) internal view returns (bool has, uint256 idx) {
        uint256 len = userVestingSchedules[user].length;
        if (len == 0) {
            return (false, 0);
        }
        return (true, len - 1);
    }


    /**
     * @dev Compute the vested amount for a given schedule at a specific timestamp.
     *      Purely reads schedule fields and caps at `schedule.totalAmount`.
     */
    function _vestedAmountAt(VestingSchedule storage schedule, uint256 timestamp) internal view returns (uint256) {
        if (timestamp < schedule.startTime) {
            return 0;
        }
        if (timestamp >= schedule.endTime) {
            return schedule.totalAmount;
        }

        uint256 timeSinceStart = timestamp - schedule.startTime;
        uint256 monthsSinceStart = timeSinceStart / (30 * 24 * 60 * 60);
        if (monthsSinceStart < 7) {
            return 0;
        }

        uint256 totalVested = 0;
        // Phase 1: 1.2% at months 7,10,13,16,19
        uint256 firstYearUnlocks = 0;
        if (monthsSinceStart >= 7) firstYearUnlocks++;
        if (monthsSinceStart >= 10) firstYearUnlocks++;
        if (monthsSinceStart >= 13) firstYearUnlocks++;
        if (monthsSinceStart >= 16) firstYearUnlocks++;
        if (monthsSinceStart >= 19) firstYearUnlocks++;
        uint256 firstYearAmount = (schedule.totalAmount * FIRST_YEAR_UNLOCK_PERCENTAGE) / 1000;
        totalVested += firstYearAmount * firstYearUnlocks;

        // Phase 2: 7% every 3 months from 22 to 49
        if (monthsSinceStart >= 22) {
            uint256 postQ5Unlocks = 0;
            for (uint256 month = 22; month <= 49; month += 3) {
                if (monthsSinceStart >= month) {
                    postQ5Unlocks++;
                }
            }
            uint256 postQ5Amount = (schedule.totalAmount * POST_Q5_UNLOCK_PERCENTAGE) / 1000;
            totalVested += postQ5Amount * postQ5Unlocks;
        }

        // Phase 3: 6% every 3 months from 52 to 61
        if (monthsSinceStart >= 52) {
            uint256 finalUnlocks = 0;
            for (uint256 month = 52; month <= 61; month += 3) {
                if (monthsSinceStart >= month) {
                    finalUnlocks++;
                }
            }
            uint256 finalAmount = (schedule.totalAmount * FINAL_UNLOCK_PERCENTAGE) / 1000;
            totalVested += finalAmount * finalUnlocks;
        }

        if (totalVested > schedule.totalAmount) {
            totalVested = schedule.totalAmount;
        }
        return totalVested;
    }

    /**
     * @notice Early release of locked tokens for a specific schedule.
     * @dev Only owner can call. Amount must not exceed the schedule's remaining locked amount.
     */
    function earlyRelease(address user, uint256 index, uint256 amount) external onlyOwner nonReentrant {
        require(index < userVestingSchedules[user].length, 'Invalid schedule index');
        require(amount > 0, 'Amount must be greater than zero');
        VestingSchedule storage schedule = userVestingSchedules[user][index];
        require(schedule.isActive, 'No active vesting schedule');

        uint256 currentTime = block.timestamp;
        uint256 vestedForSchedule = _vestedAmountAt(schedule, currentTime);
        uint256 maxUnlocked = vestedForSchedule > schedule.unlockedAmount ? vestedForSchedule : schedule.unlockedAmount;
        uint256 lockedAmountForSchedule = schedule.totalAmount > maxUnlocked ? (schedule.totalAmount - maxUnlocked) : 0;
        require(amount <= lockedAmountForSchedule, 'Amount exceeds remaining locked tokens');

        schedule.unlockedAmount += amount;
        totalUnlocked += amount;
        // mapping unchanged; latest is derived from array on reads
        emit EarlyRelease(user, amount, block.timestamp);
    }

    /**
     * @notice Emergency unlock of all remaining tokens across all active schedules of a user.
     * @dev Marks schedules inactive and sets unlockedAmount to totalAmount.
     */
    function emergencyUnlockAll(address user) external onlyOwner nonReentrant {
        (bool has, ) = _latestScheduleIndex(user);
        require(has, 'No active vesting schedule');

        VestingSchedule[] storage schedules = userVestingSchedules[user];
        uint256 totalJustUnlocked = 0;
        for (uint256 i = 0; i < schedules.length; i++) {
            VestingSchedule storage schedule = schedules[i];
            if (!schedule.isActive) {
                continue;
            }
            uint256 totalVested = _vestedAmountAt(schedule, block.timestamp);
            uint256 maxUnlocked = totalVested > schedule.unlockedAmount ? totalVested : schedule.unlockedAmount;
            uint256 lockedAmount = schedule.totalAmount > maxUnlocked ? (schedule.totalAmount - maxUnlocked) : 0;
            if (lockedAmount > 0) {
                schedule.unlockedAmount = schedule.totalAmount;
                totalJustUnlocked += lockedAmount;
                schedule.isActive = false;
            }
        }
        require(totalJustUnlocked > 0, 'No tokens left to unlock');
        totalUnlocked += totalJustUnlocked;
        // mapping unchanged; latest is derived from array on reads

        emit EmergencyUnlockAll(user, totalJustUnlocked, block.timestamp);
    }

    /**
     * @notice Modify an existing vesting schedule by index.
     * @dev Only the creator of the schedule can modify it. Increases transfer delta tokens from creator to user.
     *      New amount cannot be below the currently vested or previously unlocked amount.
     */
    function modifyVestingSchedule(address user, uint256 index, uint256 newAmount) external nonReentrant {
        require(index < userVestingSchedules[user].length, 'Invalid schedule index');
        VestingSchedule storage schedule = userVestingSchedules[user][index];
        require(schedule.isActive, 'No active vesting schedule');
        require(msg.sender == schedule.creator, 'Only schedule creator');

        uint256 currentTime = block.timestamp;
        uint256 recomputedVested = _vestedAmountAt(schedule, currentTime);
        uint256 floorAmount = schedule.unlockedAmount > recomputedVested ? schedule.unlockedAmount : recomputedVested;
        require(newAmount >= floorAmount, 'New amount less than vested');

        uint256 oldAmount = schedule.totalAmount;
        if (newAmount > oldAmount) {
            uint256 delta = newAmount - oldAmount;
            require(balanceOf(msg.sender) >= delta, 'Insufficient tokens for increase');
            _transfer(msg.sender, user, delta);
            emit TokensTransferredForVesting(user, delta, block.timestamp);
        }

        schedule.totalAmount = newAmount;
        totalAllocated = totalAllocated - oldAmount + newAmount;
        // mapping unchanged; latest is derived from array on reads
        updateUnlockedAmountsForUser(user);
        emit VestingScheduleModified(user, newAmount, block.timestamp);
    }

    /**
     * @notice Deactivate a vesting schedule by index.
     * @dev Pauses vesting accrual without deleting data.
     */
    function deactivateVestingSchedule(address user, uint256 index) external onlyOwner nonReentrant {
        require(index < userVestingSchedules[user].length, 'Invalid schedule index');
        VestingSchedule storage schedule = userVestingSchedules[user][index];
        require(schedule.isActive, 'No active vesting schedule');
        schedule.isActive = false;
        // mapping unchanged; latest is derived from array on reads
        emit VestingScheduleDeactivated(user, block.timestamp);
    }

    /**
     * @notice Reactivate a previously deactivated vesting schedule by index.
     * @dev Requires the user still has enough transferable balance to cover remaining locked tokens.
     */
    function reactivateVestingSchedule(address user, uint256 index) external onlyOwner nonReentrant {
        require(index < userVestingSchedules[user].length, 'Invalid schedule index');
        VestingSchedule storage schedule = userVestingSchedules[user][index];
        require(!schedule.isCancelled, 'Vesting schedule cancelled');
        require(!schedule.isActive, 'Vesting schedule is already active');
        require(schedule.startTime != 0, 'No vesting schedule exists');

        uint256 recomputedVested = _vestedAmountAt(schedule, block.timestamp);
        uint256 floorUnlocked = schedule.unlockedAmount > recomputedVested ? schedule.unlockedAmount : recomputedVested;
        uint256 remainingLocked = schedule.totalAmount > floorUnlocked ? (schedule.totalAmount - floorUnlocked) : 0;
        require(transferableBalance(user) >= remainingLocked, 'Insufficient balance to reactivate');

        schedule.isActive = true;
        // mapping unchanged; latest is derived from array on reads
        emit VestingScheduleReactivated(user, block.timestamp);
    }

    /**
     * @notice Cancel a vesting schedule by index.
     * @dev Permanently disables the schedule and zeroes its time fields; reduces totalAllocated by remaining locked.
     */
    function cancelVestingSchedule(address user, uint256 index) external onlyOwner nonReentrant {
        require(index < userVestingSchedules[user].length, 'Invalid schedule index');
        VestingSchedule storage schedule = userVestingSchedules[user][index];
        require(schedule.isActive, 'No active vesting schedule');

        uint256 currentTime = block.timestamp;
        uint256 vestedForSchedule = _vestedAmountAt(schedule, currentTime);
        uint256 maxUnlocked = vestedForSchedule > schedule.unlockedAmount ? vestedForSchedule : schedule.unlockedAmount;
        uint256 lockedAmount = schedule.totalAmount > maxUnlocked ? (schedule.totalAmount - maxUnlocked) : 0;

        schedule.isActive = false;
        schedule.isCancelled = true;
        schedule.startTime = 0;
        schedule.endTime = 0;

        totalAllocated -= lockedAmount;
        // mapping unchanged; latest is derived from array on reads
        emit VestingScheduleCancelled(user, lockedAmount, block.timestamp);
    }

    /**
     * @notice Toggle the `isAirdrop` flag for a schedule by index.
     */
    function toggleAirdropStatus(address user, uint256 index) external onlyOwner nonReentrant {
        require(index < userVestingSchedules[user].length, 'Invalid schedule index');
        VestingSchedule storage schedule = userVestingSchedules[user][index];
        require(schedule.isActive, 'No active vesting schedule');
        schedule.isAirdrop = !schedule.isAirdrop;
        // mapping unchanged; latest is derived from array on reads
        emit AirdropStatusToggled(user, schedule.isAirdrop, block.timestamp);
    }

    // old modifyVestingSchedule(address,uint256) removed in favor of index-based variant

    /**
     * @notice Update unlocked amounts for all participants.
     * @dev Iterates through all participants and updates their unlocked amounts.
     */
    function updateUnlockedAmounts() external onlyOwner {
        uint256 participantsLength = participants.length;
        for (uint256 i = 0; i < participantsLength; i++) {
            updateUnlockedAmountsForUser(participants[i]);
        }
    }

    /**
     * @notice Update unlocked amounts for a specific user.
     * @dev Iterates schedules and updates `unlockedAmount` based on current timestamp; emits events on changes.
     */
    function updateUnlockedAmountsForUser(address user) public {
        VestingSchedule[] storage schedules = userVestingSchedules[user];

        for (uint256 i = 0; i < schedules.length; i++) {
            VestingSchedule storage schedule = schedules[i];

            if (!schedule.isActive || schedule.startTime == 0) {
                continue;
            }

            // Calculate vested amount for this schedule
            uint256 currentTime = block.timestamp;
            if (currentTime >= schedule.endTime) {
                if (schedule.unlockedAmount < schedule.totalAmount) {
                    uint256 additional = schedule.totalAmount - schedule.unlockedAmount;
                    schedule.unlockedAmount = schedule.totalAmount;
                    totalUnlocked += additional;
                    emit TokensUnlocked(user, additional, block.timestamp);
                }
                schedule.isActive = false;
                emit VestingScheduleCompleted(user, schedule.totalAmount, block.timestamp);
                continue;
            }
            uint256 newUnlockedAmount = _vestedAmountAt(schedule, currentTime);

            if (newUnlockedAmount > schedule.unlockedAmount) {
                uint256 additionalUnlocked = newUnlockedAmount - schedule.unlockedAmount;
                schedule.unlockedAmount = newUnlockedAmount;
                totalUnlocked += additionalUnlocked;

                emit TokensUnlocked(user, additionalUnlocked, block.timestamp);
            } else if (newUnlockedAmount < schedule.unlockedAmount) {
                // Log inconsistency but don't decrease unlocked amount
                emit VestingInconsistencyDetected(user, schedule.unlockedAmount, newUnlockedAmount, block.timestamp);
            }

            // Complete schedule if fully vested
            if (newUnlockedAmount >= schedule.totalAmount && schedule.isActive) {
                schedule.isActive = false;
                emit VestingScheduleCompleted(user, schedule.totalAmount, block.timestamp);
            }
        }
        // mapping unchanged; latest is derived from array on reads
    }

    /**
     * @notice Get the total vested amount across all active schedules for a user at the current time.
     */
    function getVestedAmount(address user) public view returns (uint256) {
        VestingSchedule[] storage schedules = userVestingSchedules[user];
        uint256 aggregateVested = 0;

        for (uint256 i = 0; i < schedules.length; i++) {
            VestingSchedule storage schedule = schedules[i];
            if (!schedule.isActive || schedule.startTime == 0) {
                continue;
            }
            uint256 currentTime = block.timestamp;
            aggregateVested += _vestedAmountAt(schedule, currentTime);
        }

        return aggregateVested;
    }

    /**
     * @notice Get the stored unlocked amount aggregated across all schedules for a user.
     */
    function getUnlockedAmount(address user) external view returns (uint256) {
        VestingSchedule[] storage schedules = userVestingSchedules[user];
        uint256 total = 0;
        for (uint256 i = 0; i < schedules.length; i++) {
            total += schedules[i].unlockedAmount;
        }
        return total;
    }

    /**
     * @notice Get the currently locked amount aggregated across all active schedules for a user.
     */
    function getLockedAmount(address user) public view returns (uint256) {
        VestingSchedule[] storage schedules = userVestingSchedules[user];
        uint256 totalLocked = 0;

        for (uint256 i = 0; i < schedules.length; i++) {
            VestingSchedule storage schedule = schedules[i];
            if (!schedule.isActive) {
                continue;
            }
            uint256 currentTime = block.timestamp;
            if (currentTime >= schedule.endTime) {
                continue;
            }
            uint256 totalVested = _vestedAmountAt(schedule, currentTime);
            uint256 userUnlocked = schedule.unlockedAmount;
            uint256 maxUnlocked = totalVested > userUnlocked ? totalVested : userUnlocked;
            uint256 lockedAmount = schedule.totalAmount > maxUnlocked ? (schedule.totalAmount - maxUnlocked) : 0;
            totalLocked += lockedAmount;
        }

        return totalLocked;
    }

    /**
     * @notice Get the latest vesting schedule (last created) for a user.
     * @dev Returns zeroed fields when no schedules exist.
     */
    function getVestingSchedule(
        address user
    )
        external
        view
        returns (
            uint256 totalAmount,
            uint256 unlockedAmount,
            uint256 startTime,
            uint256 endTime,
            bool isActive,
            bool isAirdrop
        )
    {
        VestingSchedule[] storage schedules = userVestingSchedules[user];
        if (schedules.length == 0) {
            return (0, 0, 0, 0, false, false);
        }
        VestingSchedule storage schedule = schedules[schedules.length - 1];
        return (
            schedule.totalAmount,
            schedule.unlockedAmount,
            schedule.startTime,
            schedule.endTime,
            schedule.isActive,
            schedule.isAirdrop
        );
    }

    /**
     * @dev Get all participants
     */
    function getAllParticipants() external view returns (address[] memory) {
        return participants;
    }

    /**
     * @dev Get participant count
     */
    function getParticipantCount() external view returns (uint256) {
        return participants.length;
    }

    /**
     * @dev Check if a vesting schedule is complete (all tokens unlocked)
     */
    function isVestingComplete(address user) external view returns (bool) {
        VestingSchedule[] storage schedules = userVestingSchedules[user];

        if (schedules.length == 0) {
            return false;
        }

        for (uint256 i = 0; i < schedules.length; i++) {
            VestingSchedule storage schedule = schedules[i];
            if (!schedule.isActive) {
                continue;
            }
            uint256 currentTime = block.timestamp;
            if (currentTime >= schedule.endTime) {
                continue;
            }
            if (currentTime < schedule.startTime) {
                return false;
            }
            uint256 totalVested = _vestedAmountAt(schedule, currentTime);
            if (totalVested < schedule.totalAmount) {
                return false;
            }
        }

        return true;
    }

    /**
     * @dev Get vesting statistics
     */
    function getVestingStats()
        external
        view
        returns (
            uint256 totalParticipants,
            uint256 totalAllocatedTokens,
            uint256 totalUnlockedTokens,
            uint256 remainingTokens,
            bool isVestingStarted
        )
    {
        return (
            participants.length,
            totalAllocated,
            totalUnlocked,
            totalAllocated - totalUnlocked,
            participants.length > 0
        );
    }

    // Admin functions (inherited from original token)

    /**
     * @dev Update transfer tax rate
     */
    function updateTransferTaxRate(uint256 newTaxRate) external onlyOwner {
        require(newTaxRate <= MAX_TAX_RATE, 'Tax rate too high');
        // Ensure component sum does not exceed the new transfer tax rate, unless disabling tax entirely
        if (newTaxRate > 0) {
            require(
                lpContributionRate + developmentRate + marketingRate + burnRate <= newTaxRate,
                'Components exceed tax rate'
            );
        }
        transferTaxRate = newTaxRate;
        emit TransferTaxUpdated(newTaxRate);
    }

    /**
     * @dev Update LP contribution rate
     */
    function updateLPContributionRate(uint256 newRate) external onlyOwner {
        require(newRate + developmentRate + marketingRate + burnRate <= transferTaxRate, 'Components exceed tax rate');
        lpContributionRate = newRate;
        emit LPContributionRateUpdated(newRate);
    }

    /**
     * @dev Update development rate
     */
    function updateDevelopmentRate(uint256 newRate) external onlyOwner {
        require(lpContributionRate + newRate + marketingRate + burnRate <= transferTaxRate, 'Components exceed tax rate');
        developmentRate = newRate;
        emit DevelopmentRateUpdated(newRate);
    }

    /**
     * @dev Update marketing rate
     */
    function updateMarketingRate(uint256 newRate) external onlyOwner {
        require(lpContributionRate + developmentRate + newRate + burnRate <= transferTaxRate, 'Components exceed tax rate');
        marketingRate = newRate;
        emit MarketingRateUpdated(newRate);
    }

    /**
     * @dev Update burn rate
     */
    function updateBurnRate(uint256 newRate) external onlyOwner {
        require(lpContributionRate + developmentRate + marketingRate + newRate <= transferTaxRate, 'Components exceed tax rate');
        burnRate = newRate;
        emit BurnRateUpdated(newRate);
    }

    /**
     * @dev Update LP wallet
     */
    function updateLPWallet(address newWallet) external onlyOwner {
        require(newWallet != address(0), 'Invalid wallet address');
        lpWallet = newWallet;
        emit LPWalletUpdated(newWallet);
    }

    /**
     * @dev Update marketing wallet
     */
    function updateMarketingWallet(address newWallet) external onlyOwner {
        require(newWallet != address(0), 'Invalid wallet address');
        marketingWallet = newWallet;
        emit MarketingWalletUpdated(newWallet);
    }

    /**
     * @dev Update development wallet
     */
    function updateDevelopmentWallet(address newWallet) external onlyOwner {
        require(newWallet != address(0), 'Invalid wallet address');
        developmentWallet = newWallet;
        emit DevelopmentWalletUpdated(newWallet);
    }

    /**
     * @dev Update max transaction amount
     */
    function updateMaxTxAmount(uint256 newAmount) external onlyOwner {
        require(newAmount > 0, 'Max tx amount must be greater than zero');
        maxTxAmount = newAmount;
        emit MaxTxAmountUpdated(newAmount);
    }

    /**
     * @dev Exclude/include address from transfer tax
     */
    function setTaxExclusion(address account, bool excluded) external onlyOwner {
        isExcludedFromTax[account] = excluded;
        emit TaxExclusionUpdated(account, excluded);
    }

    /**
     * @dev Exclude/include address from max transaction limit
     */
    function setMaxTxExclusion(address account, bool excluded) external onlyOwner {
        isExcludedFromMaxTx[account] = excluded;
        emit MaxTxExclusionUpdated(account, excluded);
    }

    /**
     * @dev Pause token transfers
     */
    function pause() external onlyOwner {
        _pause();
    }

    /**
     * @dev Unpause token transfers
     */
    function unpause() external onlyOwner {
        _unpause();
    }

    /**
     * @dev Burn admin rights (irreversible)
     */
    function burnAdminRights() external onlyOwner whenNotPaused {
        renounceOwnership();
    }

    /**
     * @dev Get current tax breakdown
     */
    function getTaxBreakdown()
        external
        view
        returns (uint256 transferTax, uint256 lpContribution, uint256 development, uint256 marketing, uint256 burn)
    {
        return (transferTaxRate, lpContributionRate, developmentRate, marketingRate, burnRate);
    }

    /**
     * @dev Check if address is excluded from tax
     */
    function isTaxExcluded(address account) external view returns (bool) {
        return isExcludedFromTax[account];
    }

    /**
     * @dev Check if address is excluded from max transaction limit
     */
    function isMaxTxExcluded(address account) external view returns (bool) {
        return isExcludedFromMaxTx[account];
    }

    /**
     * @notice Pre-check for bulk vesting operations.
     * @param users Array of user addresses
     * @param amounts Array of token amounts
     * @return totalTokensNeeded Total tokens required for the operation
     * @return adminBalance Current admin token balance
     * @return canProceed Whether the operation can proceed
     * @return validEntries Number of valid vesting entries
     */
    function checkVestingRequirements(
        address[] calldata users,
        uint256[] calldata amounts
    ) external view returns (uint256 totalTokensNeeded, uint256 adminBalance, bool canProceed, uint256 validEntries) {
        require(users.length == amounts.length, 'Arrays length mismatch');

        totalTokensNeeded = 0;
        validEntries = 0;

        for (uint256 i = 0; i < amounts.length; i++) {
            if (users[i] != address(0) && amounts[i] > 0) {
                totalTokensNeeded += amounts[i];
                validEntries++;
            }
        }

        adminBalance = balanceOf(msg.sender);
        canProceed = adminBalance >= totalTokensNeeded;

        return (totalTokensNeeded, adminBalance, canProceed, validEntries);
    }

    /**
     * @dev Withdraw MSVP tokens held by the contract (e.g., residual taxes)
     */
    function withdrawContractTokens(address to, uint256 amount) external onlyOwner nonReentrant {
        require(to != address(0), 'Invalid address');
        require(amount > 0, 'Amount must be greater than zero');
        require(balanceOf(address(this)) >= amount, 'Insufficient contract balance');
        super._transfer(address(this), to, amount);
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_lpWallet","type":"address"},{"internalType":"address","name":"_marketingWallet","type":"address"},{"internalType":"address","name":"_developmentWallet","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"isAirdrop","type":"bool"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"AirdropStatusToggled","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":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"BurnRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"DevelopmentRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newWallet","type":"address"}],"name":"DevelopmentWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EarlyRelease","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EmergencyUnlockAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"LPContributionRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newWallet","type":"address"}],"name":"LPWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"MarketingRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newWallet","type":"address"}],"name":"MarketingWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"MaxTxAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"excluded","type":"bool"}],"name":"MaxTxExclusionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"subadmin","type":"address"},{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"SubadminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"subadmin","type":"address"},{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"SubadminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"excluded","type":"bool"}],"name":"TaxExclusionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokensTransferredForVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokensUnlocked","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTaxRate","type":"uint256"}],"name":"TransferTaxUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newWallet","type":"address"}],"name":"TreasuryWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"recordedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"calculatedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"VestingInconsistencyDetected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"lockedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"VestingScheduleCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"VestingScheduleCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"VestingScheduleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"VestingScheduleDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"VestingScheduleModified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"VestingScheduleReactivated","type":"event"},{"inputs":[],"name":"AIRDROP_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CLIFF_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINAL_UNLOCK_PERCENTAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FIRST_YEAR_UNLOCK_PERCENTAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TAX_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POST_Q5_UNLOCK_PERCENTAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TAX_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","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":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnAdminRights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"cancelVestingSchedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"checkVestingRequirements","outputs":[{"internalType":"uint256","name":"totalTokensNeeded","type":"uint256"},{"internalType":"uint256","name":"adminBalance","type":"uint256"},{"internalType":"bool","name":"canProceed","type":"bool"},{"internalType":"uint256","name":"validEntries","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"createVestingSchedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"createVestingSchedules","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"deactivateVestingSchedule","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":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"developmentRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"developmentWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"earlyRelease","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"emergencyUnlockAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllParticipants","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getLockedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getParticipantCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTaxBreakdown","outputs":[{"internalType":"uint256","name":"transferTax","type":"uint256"},{"internalType":"uint256","name":"lpContribution","type":"uint256"},{"internalType":"uint256","name":"development","type":"uint256"},{"internalType":"uint256","name":"marketing","type":"uint256"},{"internalType":"uint256","name":"burn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUnlockedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getVestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVestingAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getVestingSchedule","outputs":[{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"unlockedAmount","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isAirdrop","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVestingStats","outputs":[{"internalType":"uint256","name":"totalParticipants","type":"uint256"},{"internalType":"uint256","name":"totalAllocatedTokens","type":"uint256"},{"internalType":"uint256","name":"totalUnlockedTokens","type":"uint256"},{"internalType":"uint256","name":"remainingTokens","type":"uint256"},{"internalType":"bool","name":"isVestingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"grantSubadminRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"hasSubadminRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isExcludedFromMaxTx","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isExcludedFromTax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMaxTxExcluded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isParticipant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isTaxExcluded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isVestingComplete","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpContributionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTxAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"modifyVestingSchedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"participants","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"reactivateVestingSchedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"revokeSubadminRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"excluded","type":"bool"}],"name":"setMaxTxExclusion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"excluded","type":"bool"}],"name":"setTaxExclusion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"toggleAirdropStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAllocated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUnlocked","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferTaxRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferableBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"updateBurnRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"updateDevelopmentRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWallet","type":"address"}],"name":"updateDevelopmentWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"updateLPContributionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWallet","type":"address"}],"name":"updateLPWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"updateMarketingRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWallet","type":"address"}],"name":"updateMarketingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"updateMaxTxAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newTaxRate","type":"uint256"}],"name":"updateTransferTaxRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWallet","type":"address"}],"name":"updateTreasuryWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateUnlockedAmounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"updateUnlockedAmountsForUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userVestingSchedules","outputs":[{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"unlockedAmount","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isAirdrop","type":"bool"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"bool","name":"isCancelled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vestingSchedules","outputs":[{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"unlockedAmount","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isAirdrop","type":"bool"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"bool","name":"isCancelled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawContractTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526032600a9081556014600b55600f600c55600d556005600e5561003560646c02863c1f5cdae42f95400000006104c2565b6015555f601a555f601b5534801561004b575f5ffd5b5060405161581138038061581183398101604081905261006a916104fc565b6040518060400160405280601581526020017f4d657461536f696c566572736550726f746f636f6c00000000000000000000008152506040518060400160405280600481526020016304d5356560e41b81525081600390816100cc91906105d3565b5060046100d982826105d3565b5050506100f26100ed6102dd60201b60201c565b6102e1565b60016007556008805460ff191690556001600160a01b0383166101505760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081314081dd85b1b195d607a1b60448201526064015b60405180910390fd5b6001600160a01b0382166101a65760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964206d61726b6574696e672077616c6c657400000000000000006044820152606401610147565b6001600160a01b0381166101fc5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420646576656c6f706d656e742077616c6c65740000000000006044820152606401610147565b600f80546001600160a01b038086166001600160a01b031992831617909255601080548584169083161790556011805492841692821683179055601280549091169091179055335f818152601360209081526040808320805460ff199081166001908117909255308086528386208054831684179055868652601490945282852080548216831790559284529220805490911690911790556102ab906c02863c1f5cdae42f95400000006102fd565b6102d57f2ccf90dd7c30b80a460e25097b3c5ef613343f69ad6b2cfd3cfb644af593ca0b336103bb565b5050506106ac565b3390565b600680546001600160a01b03191690556102fa81610440565b50565b6001600160a01b0382166103535760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610147565b8060025f828254610364919061068d565b90915550506001600160a01b0382165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35b5050565b6103c58282610496565b6103b7575f8281526009602090815260408083206001600160a01b03851684529091529020805460ff191660011790556103fc3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b505050565b5f8281526009602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b5f826104dc57634e487b7160e01b5f52601260045260245ffd5b500490565b80516001600160a01b03811681146104f7575f5ffd5b919050565b5f5f5f6060848603121561050e575f5ffd5b610517846104e1565b9250610525602085016104e1565b9150610533604085016104e1565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061056457607f821691505b60208210810361058257634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561049157805f5260205f20601f840160051c810160208510156105ad5750805b601f840160051c820191505b818110156105cc575f81556001016105b9565b5050505050565b81516001600160401b038111156105ec576105ec61053c565b610600816105fa8454610550565b84610588565b6020601f821160018114610632575f831561061b5750848201515b5f19600385901b1c1916600184901b1784556105cc565b5f84815260208120601f198516915b828110156106615787850151825560209485019460019092019101610641565b508482101561067e57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156104bc57634e487b7160e01b5f52601160045260245ffd5b615158806106b95f395ff3fe608060405234801561000f575f5ffd5b5060043610610514575f3560e01c80637c791a28116102a5578063aa741bec1161016c578063cdd712da116100d5578063e30c39781161008f578063e30c397814610c10578063ec81b7b514610c21578063f023f57314610c5a578063f2fde38b14610c6d578063fbc10c5514610c80578063fdb20ccb14610c93575f5ffd5b8063cdd712da14610b85578063d12e776c14610b8d578063d547741f14610bc4578063d5a73fdd14610bd7578063dd62ed3e14610bea578063e24de5cf14610bfd575f5ffd5b8063b3daa65211610126578063b3daa65214610b20578063b65d08b014610b2a578063ba87a7c914610b33578063bed9985014610b47578063c04a541414610b50578063cb4ca63114610b63575f5ffd5b8063aa741bec14610ab9578063aacebbe314610acc578063ab4196b214610adf578063ad60572914610af2578063ae8f84a614610afa578063aef3d38614610b0d575f5ffd5b806391d148541161020e578063a217fddf116101c8578063a217fddf14610a67578063a457c2d714610a6e578063a51c9ace14610a81578063a5a1f92814610a8a578063a779d08014610a9d578063a9059cbb14610aa6575f5ffd5b806391d14854146109c0578063929066f5146109d3578063929ec537146109f557806395058acc14610a0857806395d89b4114610a1b5780639f82906314610a23575f5ffd5b80638a857bc11161025f5780638a857bc1146109645780638c0b5e22146109775780638cbc6cbe146109805780638da5cb5b146109935780638fa81732146109a4578063902d55a5146109ac575f5ffd5b80637c791a28146108fd578063809d458d1461090657806381e21e051461091957806382b17be014610921578063838a676f146109535780638456cb591461095c575f5ffd5b8063419544a0116103e95780636303516c1161035257806370a082311161030c57806370a0823114610894578063715018a6146108a757806371dd7497146108af57806375f0a874146108da57806378d10f44146108ed57806379ba5097146108f5575f5ffd5b80636303516c14610805578063640e7aef14610818578063658c27a91461082b57806369ec8e9c1461084d5780636aa22091146108785780636c24fc751461088b575f5ffd5b8063572a1c96116103a3578063572a1c961461075c57806358615c1b1461076f5780635b3317a8146107825780635c975abb1461078a5780636152d848146107955780636256d181146107f2575f5ffd5b8063419544a0146106f4578063420d4a021461070757806345f7f2491461071a5780634626402b14610723578063521dbf651461073657806354d0c09214610749575f5ffd5b80632654cccd1161048b578063343706a411610445578063343706a41461067557806335c1d3491461068857806336568abe146106b357806339509351146106c65780633de17434146106d95780633f4ba83a146106ec575f5ffd5b80632654cccd146106125780632b7887871461061a5780632f2ff15d1461062d578063311ae7ec14610640578063313ce56714610653578063336ac67314610662575f5ffd5b806318d49861116104dc57806318d498611461058f578063195ec9ee146105a257806322b54d39146105b757806323b872dd146105ca578063248a9ca3146105dd57806325ad3198146105ff575f5ffd5b806301ffc9a71461051857806306fdde0314610540578063095ea7b3146105555780630be41d151461056857806318160ddd1461057d575b5f5ffd5b61052b610526366004614b1e565b610cf5565b60405190151581526020015b60405180910390f35b610548610d2b565b6040516105379190614b45565b61052b610563366004614b90565b610dbb565b61057b610576366004614b90565b610dd2565b005b6002545b604051908152602001610537565b61057b61059d366004614bb8565b610efb565b6105aa610f66565b6040516105379190614bf1565b61057b6105c5366004614c3c565b610fc5565b61052b6105d8366004614c55565b61118c565b6105816105eb366004614c8f565b5f9081526009602052604090206001015490565b61057b61060d366004614c8f565b6111af565b61057b61123c565b61057b610628366004614c8f565b611288565b61057b61063b366004614ca6565b61130e565b61057b61064e366004614c3c565b611337565b60405160128152602001610537565b61057b610670366004614bb8565b6113c9565b61057b610683366004614b90565b61142c565b61069b610696366004614c8f565b6115ac565b6040516001600160a01b039091168152602001610537565b61057b6106c1366004614ca6565b6115d4565b61052b6106d4366004614b90565b61164e565b6105816106e7366004614c3c565b61166f565b61057b611724565b61057b610702366004614b90565b611736565b610581610715366004614c3c565b611c22565b610581601a5481565b60125461069b906001600160a01b031681565b61057b610744366004614b90565b611c7c565b61057b610757366004614cd0565b611d3e565b61057b61076a366004614c8f565b611f19565b61057b61077d366004614c8f565b611f9e565b610581603c81565b60085460ff1661052b565b6107a86107a3366004614b90565b61206f565b60408051988952602089019790975295870194909452606086019290925215156080850152151560a08401526001600160a01b031660c0830152151560e082015261010001610537565b61057b610800366004614c8f565b6120df565b600f5461069b906001600160a01b031681565b61052b610826366004614c3c565b61217b565b61052b610839366004614c3c565b60146020525f908152604090205460ff1681565b61052b61085b366004614c3c565b6001600160a01b03165f9081526013602052604090205460ff1690565b61057b610886366004614d48565b61223e565b610581600b5481565b6105816108a2366004614c3c565b6129a4565b61057b6129c1565b61052b6108bd366004614c3c565b6001600160a01b03165f9081526014602052604090205460ff1690565b60105461069b906001600160a01b031681565b610581604681565b61057b6129d2565b610581600c5481565b61057b610914366004614c3c565b612a49565b61057b612ac5565b610929612add565b6040805195865260208601949094529284019190915260608301521515608082015260a001610537565b610581600d5481565b61057b612b14565b6105816be8a5010cf2a411214000000081565b61058160155481565b61057b61098e366004614cd0565b612b24565b6005546001600160a01b031661069b565b610581606481565b6105816c02863c1f5cdae42f954000000081565b61052b6109ce366004614ca6565b612dbb565b61052b6109e1366004614c3c565b60196020525f908152604090205460ff1681565b610581610a03366004614c3c565b612de5565b61057b610a16366004614b90565b612eb3565b610548612f9f565b610a36610a31366004614c3c565b612fae565b60408051968752602087019590955293850192909252606084015215156080830152151560a082015260c001610537565b6105815f81565b61052b610a7c366004614b90565b61305f565b6105816103e881565b61057b610a98366004614c3c565b6130d9565b610581601b5481565b61052b610ab4366004614b90565b613168565b61057b610ac7366004614c3c565b613175565b61057b610ada366004614c3c565b613431565b610581610aed366004614c3c565b6134ad565b601854610581565b61057b610b08366004614b90565b613525565b61052b610b1b366004614c3c565b6137c0565b61058162ed4e0081565b610581600a5481565b6105815f5160206151035f395f51905f5281565b610581600e5481565b60115461069b906001600160a01b031681565b61052b610b71366004614c3c565b60136020525f908152604090205460ff1681565b610581600c81565b600a54600b54600c54600d54600e54604080519586526020860194909452928401919091526060830152608082015260a001610537565b61057b610bd2366004614ca6565b6137d8565b610581610be5366004614c3c565b6137fc565b610581610bf8366004614db4565b613887565b61057b610c0b366004614c8f565b6138b1565b6006546001600160a01b031661069b565b610c34610c2f366004614d48565b613937565b604080519485526020850193909352901515918301919091526060820152608001610537565b61057b610c68366004614c3c565b613a46565b61057b610c7b366004614c3c565b613ac2565b61057b610c8e366004614c3c565b613b33565b6107a8610ca1366004614c3c565b60166020525f9081526040902080546001820154600283015460038401546004909401549293919290919060ff8082169161010081048216916001600160a01b036201000083041691600160b01b90041688565b5f6001600160e01b03198216637965db0b60e01b1480610d2557506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060038054610d3a90614ddc565b80601f0160208091040260200160405190810160405280929190818152602001828054610d6690614ddc565b8015610db15780601f10610d8857610100808354040283529160200191610db1565b820191905f5260205f20905b815481529060010190602001808311610d9457829003601f168201915b5050505050905090565b5f33610dc8818585613baf565b5060019392505050565b610dda613cd2565b610de2613d2c565b6001600160a01b0382165f908152601760205260409020548110610e215760405162461bcd60e51b8152600401610e1890614e14565b60405180910390fd5b6001600160a01b0382165f908152601760205260408120805483908110610e4a57610e4a614e44565b5f9182526020909120600590910201600481015490915060ff16610e805760405162461bcd60e51b8152600401610e1890614e58565b60048101805460ff610100808304821615810261ff00199093169290921792839055604080519290930416151581524260208201526001600160a01b038516917fc9031c29f273e1fcfe9c1bcaa668b10bc343a9e84ad019f7dc3665ec8a0994d191015b60405180910390a250610ef76001600755565b5050565b610f03613cd2565b6001600160a01b0382165f81815260136020908152604091829020805460ff19168515159081179091558251938452908301527f057dc60ecf6df48e0f4af40ef0f88074d41e0ce54a1fef20925cd23c6de0386091015b60405180910390a15050565b60606018805480602002602001604051908101604052809291908181526020018280548015610db157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610f9e575050505050905090565b610fcd613cd2565b610fd5613d2c565b5f610fdf82613d85565b50905080610fff5760405162461bcd60e51b8152600401610e1890614e58565b6001600160a01b0382165f90815260176020526040812090805b82548110156110d3575f83828154811061103557611035614e44565b5f9182526020909120600590910201600481015490915060ff1661105957506110cb565b5f6110648242613dc7565b90505f8260010154821161107c57826001015461107e565b815b90505f81845f015411611091575f61109e565b835461109e908390614ea3565b905080156110c657835460018501556110b78187614eb6565b60048501805460ff1916905595505b505050505b600101611019565b505f81116111235760405162461bcd60e51b815260206004820152601860248201527f4e6f20746f6b656e73206c65667420746f20756e6c6f636b00000000000000006044820152606401610e18565b80601b5f8282546111349190614eb6565b9091555050604080518281524260208201526001600160a01b038616917f99b50e15cf191f04bfbfd29e284810ecd067636b6c33cbf6134d6d65beb5a6d9910160405180910390a25050506111896001600755565b50565b5f33611199858285613fce565b6111a4858585614046565b506001949350505050565b6111b7613cd2565b600a54600e54600d5483600b546111ce9190614eb6565b6111d89190614eb6565b6111e29190614eb6565b11156112005760405162461bcd60e51b8152600401610e1890614ec9565b600c8190556040518181527f5e10fd5ddf113b5355f7a23f3d729f6e938dd4f13642c82f11469afa02f8548a906020015b60405180910390a150565b611244613cd2565b6018545f5b81811015610ef7576112806018828154811061126757611267614e44565b5f918252602090912001546001600160a01b0316613175565b600101611249565b611290613cd2565b600a5481600d54600c54600b546112a79190614eb6565b6112b19190614eb6565b6112bb9190614eb6565b11156112d95760405162461bcd60e51b8152600401610e1890614ec9565b600e8190556040518181527f47863b595116a31383855975a4078913dce7881e717b75a06ced2db5d534ff7890602001611231565b5f828152600960205260409020600101546113288161430c565b6113328383614316565b505050565b61133f613cd2565b6001600160a01b0381166113655760405162461bcd60e51b8152600401610e1890614f00565b61137c5f5160206151035f395f51905f5282614316565b6001600160a01b0381165f81815260136020526040808220805460ff19166001179055513392917fbefa07af2dfa4c1c71661acd889424e95a2f805bdbf833573f60374e52d7130691a350565b6113d1613cd2565b6001600160a01b0382165f81815260146020908152604091829020805460ff19168515159081179091558251938452908301527f4fde41d38f7a4818cef6b418d1048204bae25e6104e02ddf7f89c3c233b3eda99101610f5a565b611434613cd2565b61143c613d2c565b6001600160a01b0382165f9081526017602052604090205481106114725760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0382165f90815260176020526040812080548390811061149b5761149b614e44565b5f9182526020909120600590910201600481015490915060ff166114d15760405162461bcd60e51b8152600401610e1890614e58565b425f6114dd8383613dc7565b90505f836001015482116114f55783600101546114f7565b815b90505f81855f01541161150a575f611517565b8454611517908390614ea3565b60048601805460ff60ff60b01b011916600160b01b1790555f6002870181905560038701819055601a80549293508392909190611555908490614ea3565b9091555050604080518281524260208201526001600160a01b038916917f7ccdce830ffcfd4ae5baac3fbca1ba04c1135db945a98e65924c2ad7bd1a4422910160405180910390a25050505050610ef76001600755565b601881815481106115bb575f80fd5b5f918252602090912001546001600160a01b0316905081565b6001600160a01b03811633146116445760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610e18565b610ef7828261439b565b5f33610dc88185856116608383613887565b61166a9190614eb6565b613baf565b6001600160a01b0381165f9081526019602052604081205460ff1661169557505f919050565b6001600160a01b0382165f90815260176020526040812090805b825481101561171c578281815481106116ca576116ca614e44565b5f91825260209091206004600590920201015460ff1615611714578281815481106116f7576116f7614e44565b905f5260205f2090600502015f0154826117119190614eb6565b91505b6001016116af565b509392505050565b61172c613cd2565b611734614401565b565b5f5160206151035f395f51905f5261174d8161430c565b611755613d2c565b6001600160a01b0383166117a25760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642075736572206164647265737360601b6044820152606401610e18565b5f82116117c15760405162461bcd60e51b8152600401610e1890614f29565b816117cb336129a4565b10156118195760405162461bcd60e51b815260206004820152601f60248201527f496e73756666696369656e7420746f6b656e7320666f722076657374696e67006044820152606401610e18565b611824338484614046565b5f5f600a541180156118455750335f9081526013602052604090205460ff16155b801561186957506001600160a01b0384165f9081526013602052604090205460ff16155b90505f81611877578361189c565b6103e8600a54856118889190614f5e565b6118929190614f75565b61189c9085614ea3565b604080518281524260208201529192506001600160a01b038716917f95f5297f9f827597da7117f9efc0ab78db5461cff01c5f842aac80d292df34e0910160405180910390a2425f6118f28263096c9900614eb6565b90505f6040518061010001604052808581526020015f8152602001848152602001838152602001600115158152602001600115158152602001336001600160a01b031681526020015f151581525090508060165f8a6001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f01556020820151816001015560408201518160020155606082015181600301556080820151816004015f6101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548160ff02191690831515021790555060c08201518160040160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160040160166101000a81548160ff02191690831515021790555090505060175f896001600160a01b03166001600160a01b031681526020019081526020015f2081908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f01556020820151816001015560408201518160020155606082015181600301556080820151816004015f6101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548160ff02191690831515021790555060c08201518160040160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160040160166101000a81548160ff021916908315150217905550505060195f896001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff16611bb0576018805460018082019092557fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e0180546001600160a01b0319166001600160a01b038b169081179091555f908152601960205260409020805460ff191690911790555b83601a5f828254611bc19190614eb6565b909155505060408051858152602081018590529081018390526001600160a01b038916907f892f1a841b10e4b041cc41d8cc47c6a6049f1ff5fa272ddf47a0aa5ad8f59d13906060015b60405180910390a250505050506113326001600755565b6001600160a01b0381165f90815260176020526040812081805b825481101561171c57828181548110611c5757611c57614e44565b905f5260205f2090600502016001015482611c729190614eb6565b9150600101611c3c565b611c84613cd2565b611c8c613d2c565b6001600160a01b038216611cb25760405162461bcd60e51b8152600401610e1890614f00565b5f8111611cd15760405162461bcd60e51b8152600401610e1890614f29565b80611cdb306129a4565b1015611d295760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606401610e18565b611d34308383614453565b610ef76001600755565b611d46613cd2565b611d4e613d2c565b6001600160a01b0383165f908152601760205260409020548210611d845760405162461bcd60e51b8152600401610e1890614e14565b5f8111611da35760405162461bcd60e51b8152600401610e1890614f29565b6001600160a01b0383165f908152601760205260408120805484908110611dcc57611dcc614e44565b5f9182526020909120600590910201600481015490915060ff16611e025760405162461bcd60e51b8152600401610e1890614e58565b425f611e0e8383613dc7565b90505f83600101548211611e26578360010154611e28565b815b90505f81855f015411611e3b575f611e48565b8454611e48908390614ea3565b905080861115611ea95760405162461bcd60e51b815260206004820152602660248201527f416d6f756e7420657863656564732072656d61696e696e67206c6f636b656420604482015265746f6b656e7360d01b6064820152608401610e18565b85856001015f828254611ebc9190614eb6565b9250508190555085601b5f828254611ed49190614eb6565b9091555050604080518781524260208201526001600160a01b038a16917f5f2c0ba2f60ed002c855ce66ef5bc7c00a85b717d286d415a2bcb5f8ed55796b9101611c0b565b611f21613cd2565b600a54600e54600d54600c54611f379085614eb6565b611f419190614eb6565b611f4b9190614eb6565b1115611f695760405162461bcd60e51b8152600401610e1890614ec9565b600b8190556040518181527f03d5690a884c4427453657817210296ad15540b3dd7e88a20adba9fdfe04f74f90602001611231565b611fa6613cd2565b6064811115611feb5760405162461bcd60e51b81526020600482015260116024820152700a8c2f040e4c2e8ca40e8dede40d0d2ced607b1b6044820152606401610e18565b801561203a5780600e54600d54600c54600b546120089190614eb6565b6120129190614eb6565b61201c9190614eb6565b111561203a5760405162461bcd60e51b8152600401610e1890614ec9565b600a8190556040518181527fe9b79e1a6c2dc43b4c0c6ff01ce9e3332d810e482270f464c0a21ad6c5fc6de390602001611231565b6017602052815f5260405f208181548110612088575f80fd5b5f91825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff8082169161010081048216916001600160a01b036201000083041691600160b01b90041688565b6120e7613cd2565b5f81116121465760405162461bcd60e51b815260206004820152602760248201527f4d617820747820616d6f756e74206d7573742062652067726561746572207468604482015266616e207a65726f60c81b6064820152608401610e18565b60158190556040518181527f947f344d56e1e8c70dc492fb94c4ddddd490c016aab685f5e7e47b2e85cb44cf90602001611231565b6001600160a01b0381165f908152601760205260408120805482036121a257505f92915050565b5f5b8154811015610dc8575f8282815481106121c0576121c0614e44565b5f9182526020909120600590910201600481015490915060ff166121e45750612236565b6003810154429081106121f8575050612236565b816002015481101561220f57505f95945050505050565b5f61221a8383613dc7565b835490915081101561223257505f9695505050505050565b5050505b6001016121a4565b5f5160206151035f395f51905f526122558161430c565b61225d613d2c565b8382146122a55760405162461bcd60e51b8152602060048201526016602482015275082e4e4c2f2e640d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606401610e18565b836122e15760405162461bcd60e51b815260206004820152600c60248201526b456d7074792061727261797360a01b6044820152606401610e18565b5f805b83811015612376575f8787838181106122ff576122ff614e44565b90506020020160208101906123149190614c3c565b6001600160a01b03161415801561234257505f85858381811061233957612339614e44565b90506020020135115b1561236e5784848281811061235957612359614e44565b905060200201358261236b9190614eb6565b91505b6001016122e4565b5080612381336129a4565b10156123db5760405162461bcd60e51b8152602060048201526024808201527f496e73756666696369656e7420746f6b656e7320666f722062756c6b2076657360448201526374696e6760e01b6064820152608401610e18565b425f6123eb8263096c9900614eb6565b90505f5b8781101561298f575f89898381811061240a5761240a614e44565b905060200201602081019061241f9190614c3c565b6001600160a01b03161415801561244d57505f87878381811061244457612444614e44565b90506020020135115b156129875761249b338a8a8481811061246857612468614e44565b905060200201602081019061247d9190614c3c565b89898581811061248f5761248f614e44565b90506020020135614046565b5f5f600a541180156124bc5750335f9081526013602052604090205460ff16155b801561250b575060135f8b8b858181106124d8576124d8614e44565b90506020020160208101906124ed9190614c3c565b6001600160a01b0316815260208101919091526040015f205460ff16155b90505f816125315788888481811061252557612525614e44565b90506020020135612587565b6103e8600a548a8a8681811061254957612549614e44565b9050602002013561255a9190614f5e565b6125649190614f75565b89898581811061257657612576614e44565b905060200201356125879190614ea3565b90508a8a8481811061259b5761259b614e44565b90506020020160208101906125b09190614c3c565b6001600160a01b03167f95f5297f9f827597da7117f9efc0ab78db5461cff01c5f842aac80d292df34e082426040516125f3929190918252602082015260400190565b60405180910390a260408051610100810182528281525f602082018190529181018790526060810186905260016080820181905260a08201523360c082015260e081018290529081906016908e8e8881811061265157612651614e44565b90506020020160208101906126669190614c3c565b6001600160a01b03908116825260208083019390935260409182015f908120855181559385015160018501559184015160028401556060840151600384015560808401516004909301805460a086015160c087015160e09097015161ffff1990921695151561ff00191695909517610100951515959095029490941762010000600160b81b03191662010000959092169490940260ff60b01b191617600160b01b92151592909202919091179091556017908d8d8781811061272a5761272a614e44565b905060200201602081019061273f9190614c3c565b6001600160a01b03908116825260208083019390935260409182015f908120805460018181018355918352858320875160059092020190815594860151908501559184015160028401556060840151600384015560808401516004909301805460a086015160c087015160e08801511515600160b01b0260ff60b01b199190951662010000021662010000600160b81b03199115156101000261ff00199715159790971661ffff1990931692909217959095179490941693909317179091556019908d8d8781811061281357612813614e44565b90506020020160208101906128289190614c3c565b6001600160a01b0316815260208101919091526040015f205460ff166128f75760188c8c8681811061285c5761285c614e44565b90506020020160208101906128719190614c3c565b8154600180820184555f9384526020842090910180546001600160a01b0319166001600160a01b039390931692909217909155906019908e8e888181106128ba576128ba614e44565b90506020020160208101906128cf9190614c3c565b6001600160a01b0316815260208101919091526040015f20805460ff19169115159190911790555b81601a5f8282546129089190614eb6565b909155508c90508b8581811061292057612920614e44565b90506020020160208101906129359190614c3c565b60408051848152602081018990529081018790526001600160a01b0391909116907f892f1a841b10e4b041cc41d8cc47c6a6049f1ff5fa272ddf47a0aa5ad8f59d139060600160405180910390a25050505b6001016123ef565b5050505061299d6001600755565b5050505050565b6001600160a01b0381165f90815260208190526040812054610d25565b6129c9613cd2565b6117345f61457b565b60065433906001600160a01b03168114612a405760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610e18565b6111898161457b565b612a51613cd2565b6001600160a01b038116612a775760405162461bcd60e51b8152600401610e1890614f94565b601280546001600160a01b0319166001600160a01b0383169081179091556040519081527f97c79b3848e51f57983ac89e4403452655c8d83ceba8199011de63a74f60d1a790602001611231565b612acd613cd2565b612ad5614594565b6117346129c1565b5f5f5f5f5f601880549050601a54601b54601b54601a54612afe9190614ea3565b6018549399929850909650945090151592509050565b612b1c613cd2565b6117346145da565b612b2c613d2c565b6001600160a01b0383165f908152601760205260409020548210612b625760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0383165f908152601760205260408120805484908110612b8b57612b8b614e44565b5f9182526020909120600590910201600481015490915060ff16612bc15760405162461bcd60e51b8152600401610e1890614e58565b60048101546201000090046001600160a01b03163314612c1b5760405162461bcd60e51b815260206004820152601560248201527427b7363c9039b1b432b23ab6329031b932b0ba37b960591b6044820152606401610e18565b425f612c278383613dc7565b90505f81846001015411612c3b5781612c41565b83600101545b905080851015612c935760405162461bcd60e51b815260206004820152601b60248201527f4e657720616d6f756e74206c657373207468616e2076657374656400000000006044820152606401610e18565b835480861115612d52575f612ca88288614ea3565b905080612cb4336129a4565b1015612d025760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420746f6b656e7320666f7220696e6372656173656044820152606401610e18565b612d0d338a83614046565b604080518281524260208201526001600160a01b038b16917f95f5297f9f827597da7117f9efc0ab78db5461cff01c5f842aac80d292df34e0910160405180910390a2505b858555601a548690612d65908390614ea3565b612d6f9190614eb6565b601a55612d7b88613175565b604080518781524260208201526001600160a01b038a16917fcb7620a89fe7effd1ec7a600cae454314b7a51b26f215d7ad59f5070fad46dde9101611c0b565b5f9182526009602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6001600160a01b0381165f90815260176020526040812081805b825481101561171c575f838281548110612e1b57612e1b614e44565b5f9182526020909120600590910201600481015490915060ff16612e3f5750612eab565b600381015442908110612e53575050612eab565b5f612e5e8383613dc7565b60018401549091505f818311612e745781612e76565b825b90505f81865f015411612e89575f612e96565b8554612e96908390614ea3565b9050612ea28189614eb6565b97505050505050505b600101612dff565b612ebb613cd2565b612ec3613d2c565b6001600160a01b0382165f908152601760205260409020548110612ef95760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0382165f908152601760205260408120805483908110612f2257612f22614e44565b5f9182526020909120600590910201600481015490915060ff16612f585760405162461bcd60e51b8152600401610e1890614e58565b60048101805460ff191690556040514281526001600160a01b038416907f27afda27f49489e1414b933acd435beef4ac058ffa59989c360ac892def427fc90602001610ee4565b606060048054610d3a90614ddc565b6001600160a01b0381165f908152601760205260408120805482918291829182918291908203612ff0575f5f5f5f5f5f96509650965096509650965050613056565b80545f90829061300290600190614ea3565b8154811061301257613012614e44565b5f91825260209091206005909102018054600182015460028301546003840154600490940154929b50909950975090955060ff808216955061010090910416925050505b91939550919395565b5f338161306c8286613887565b9050838110156130cc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610e18565b6111a48286868403613baf565b6130e1613cd2565b6001600160a01b0381166131075760405162461bcd60e51b8152600401610e1890614f00565b61311e5f5160206151035f395f51905f528261439b565b6001600160a01b0381165f81815260136020526040808220805460ff19169055513392917f827af9c874807d9353cf2b4c17319dba2ff27651355b0e78fecc29f4e386ba9691a350565b5f33610dc8818585614046565b6001600160a01b0381165f908152601760205260408120905b8154811015611332575f8282815481106131aa576131aa614e44565b5f9182526020909120600590910201600481015490915060ff1615806131d257506002810154155b156131dd5750613429565b6003810154429081106132c85781546001830154101561327057600182015482545f9161320991614ea3565b83546001850155601b805491925082915f90613226908490614eb6565b9091555050604080518281524260208201526001600160a01b038816917f89882ad382a3742d4db24e4dabc5000c5852aed762904db28442e4e1630a1d07910160405180910390a2505b60048201805460ff191690558154604080519182524260208301526001600160a01b038716917f2f2bd35e8c85fab03ec786f38a3e9424e1c4823c8a5cbd23a32664dd27dfdd22910160405180910390a25050613429565b5f6132d38383613dc7565b9050826001015481111561335c575f8360010154826132f29190614ea3565b905081846001018190555080601b5f82825461330e9190614eb6565b9091555050604080518281524260208201526001600160a01b038916917f89882ad382a3742d4db24e4dabc5000c5852aed762904db28442e4e1630a1d07910160405180910390a2506133b9565b82600101548110156133b9576001830154604080519182526020820183905242908201526001600160a01b038716907f102441b567edf9782e9aa2ce227915f2e7aa6d6203be9970bc6dbbf655f488d79060600160405180910390a25b825481108015906133ce5750600483015460ff165b156134255760048301805460ff191690558254604080519182524260208301526001600160a01b038816917f2f2bd35e8c85fab03ec786f38a3e9424e1c4823c8a5cbd23a32664dd27dfdd22910160405180910390a25b5050505b60010161318e565b613439613cd2565b6001600160a01b03811661345f5760405162461bcd60e51b8152600401610e1890614f94565b601080546001600160a01b0319166001600160a01b0383169081179091556040519081527fbf86feedee5b30c30a8243bd21deebb704d141478d39b1be04fe5ee739f214e790602001611231565b6001600160a01b0381165f9081526019602052604081205460ff1615613503576001600160a01b0382165f90815260208190526040812054906134ef84612de5565b90506134fb8183614ea3565b949350505050565b6001600160a01b0382165f90815260208190526040902054610d25565b919050565b61352d613cd2565b613535613d2c565b6001600160a01b0382165f90815260176020526040902054811061356b5760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0382165f90815260176020526040812080548390811061359457613594614e44565b905f5260205f20906005020190508060040160169054906101000a900460ff16156136015760405162461bcd60e51b815260206004820152601a60248201527f56657374696e67207363686564756c652063616e63656c6c65640000000000006044820152606401610e18565b600481015460ff16156136615760405162461bcd60e51b815260206004820152602260248201527f56657374696e67207363686564756c6520697320616c72656164792061637469604482015261766560f01b6064820152608401610e18565b80600201545f036136b45760405162461bcd60e51b815260206004820152601a60248201527f4e6f2076657374696e67207363686564756c65206578697374730000000000006044820152606401610e18565b5f6136bf8242613dc7565b90505f818360010154116136d357816136d9565b82600101545b90505f81845f0154116136ec575f6136f9565b83546136f9908390614ea3565b905080613705876134ad565b101561375e5760405162461bcd60e51b815260206004820152602260248201527f496e73756666696369656e742062616c616e636520746f207265616374697661604482015261746560f01b6064820152608401610e18565b60048401805460ff191660011790556040516001600160a01b038716907f3bfe7418887a68023ea2000b535ae874d807ced1c0e7b6e904791012bdda7165906137aa9042815260200190565b60405180910390a250505050610ef76001600755565b5f610d255f5160206151035f395f51905f5283612dbb565b5f828152600960205260409020600101546137f28161430c565b611332838361439b565b6001600160a01b0381165f90815260176020526040812081805b825481101561171c575f83828154811061383257613832614e44565b5f9182526020909120600590910201600481015490915060ff16158061385a57506002810154155b15613865575061387f565b426138708282613dc7565b61387a9085614eb6565b935050505b600101613816565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6138b9613cd2565b600a54600e5482600c54600b546138d09190614eb6565b6138da9190614eb6565b6138e49190614eb6565b11156139025760405162461bcd60e51b8152600401610e1890614ec9565b600d8190556040518181527fe5493206f305f48f22963f38bf60fcb4685e3af5843619da148412268d2f0a7090602001611231565b5f8080808685146139835760405162461bcd60e51b8152602060048201526016602482015275082e4e4c2f2e640d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606401610e18565b505f925082805b85811015613a29575f8989838181106139a5576139a5614e44565b90506020020160208101906139ba9190614c3c565b6001600160a01b0316141580156139e857505f8787838181106139df576139df614e44565b90506020020135115b15613a21578686828181106139ff576139ff614e44565b9050602002013585613a119190614eb6565b945081613a1d81614fc4565b9250505b60010161398a565b50613a33336129a4565b9250838310159150945094509450949050565b613a4e613cd2565b6001600160a01b038116613a745760405162461bcd60e51b8152600401610e1890614f94565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527f59fd076cdcd0c12d650e7d16898047308777be9d03b00a2907a56cb113412be590602001611231565b613aca613cd2565b600680546001600160a01b0383166001600160a01b03199091168117909155613afb6005546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b613b3b613cd2565b6001600160a01b038116613b615760405162461bcd60e51b8152600401610e1890614f94565b600f80546001600160a01b0319166001600160a01b0383169081179091556040519081527f71bcdff234e981b4f1f8acf4fbf6c9aab4fb20bdc744ba24715786dbadcee1aa90602001611231565b6001600160a01b038316613c115760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610e18565b6001600160a01b038216613c725760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610e18565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6005546001600160a01b031633146117345760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e18565b600260075403613d7e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e18565b6002600755565b6001600160a01b0381165f908152601760205260408120548190808203613db157505f93849350915050565b6001613dbd8183614ea3565b9250925050915091565b5f8260020154821015613ddb57505f610d25565b82600301548210613dee57508154610d25565b5f836002015483613dff9190614ea3565b90505f613e0f62278d0083614f75565b90506007811015613e24575f92505050610d25565b5f8060078310613e3c5780613e3881614fc4565b9150505b600a8310613e525780613e4e81614fc4565b9150505b600d8310613e685780613e6481614fc4565b9150505b60108310613e7e5780613e7a81614fc4565b9150505b60138310613e945780613e9081614fc4565b9150505b5f6103e8600c895f0154613ea89190614f5e565b613eb29190614f75565b9050613ebe8282614f5e565b613ec89084614eb6565b925060168410613f3f575f60165b60318111613f0557808610613ef35781613eef81614fc4565b9250505b613efe600382614eb6565b9050613ed6565b505f6103e860468b5f0154613f1a9190614f5e565b613f249190614f75565b9050613f308282614f5e565b613f3a9086614eb6565b945050505b60348410613fb4575f60345b603d8111613f7a57808610613f685781613f6481614fc4565b9250505b613f73600382614eb6565b9050613f4b565b505f6103e8603c8b5f0154613f8f9190614f5e565b613f999190614f75565b9050613fa58282614f5e565b613faf9086614eb6565b945050505b8754831115613fc257875492505b50909695505050505050565b5f613fd98484613887565b90505f19811461404057818110156140335760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610e18565b6140408484848403613baf565b50505050565b61404e614594565b6001600160a01b0383166140745760405162461bcd60e51b8152600401610e1890614fdc565b6001600160a01b03821661409a5760405162461bcd60e51b8152600401610e1890615021565b5f81116140fb5760405162461bcd60e51b815260206004820152602960248201527f5472616e7366657220616d6f756e74206d7573742062652067726561746572206044820152687468616e207a65726f60b81b6064820152608401610e18565b6001600160a01b0383165f9081526019602052604090205460ff16156141245761412483613175565b6001600160a01b0382165f9081526019602052604090205460ff161561414d5761414d82613175565b5f614157846134ad565b9050818110156141b35760405162461bcd60e51b815260206004820152602160248201527f496e73756666696369656e74207472616e7366657261626c652062616c616e636044820152606560f81b6064820152608401610e18565b6001600160a01b0384165f9081526014602052604090205460ff161580156141f357506001600160a01b0383165f9081526014602052604090205460ff16155b15614260576015548211156142605760405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657220616d6f756e742065786365656473206d6178207472616e60448201526c1cd858dd1a5bdb881b1a5b5a5d609a1b6064820152608401610e18565b600a545f901580159061428b57506001600160a01b0385165f9081526013602052604090205460ff16155b80156142af57506001600160a01b0384165f9081526013602052604090205460ff16155b156142d2576103e8600a54846142c59190614f5e565b6142cf9190614f75565b90505b5f6142dd8285614ea3565b90506142ea868683614453565b8115614304576142fb863084614453565b61430482614617565b505050505050565b611189813361474c565b6143208282612dbb565b610ef7575f8281526009602090815260408083206001600160a01b03851684529091529020805460ff191660011790556143573390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6143a58282612dbb565b15610ef7575f8281526009602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6144096147a5565b6008805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0383166144795760405162461bcd60e51b8152600401610e1890614fdc565b6001600160a01b03821661449f5760405162461bcd60e51b8152600401610e1890615021565b6001600160a01b0383165f90815260208190526040902054818110156145165760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610e18565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3614040565b600680546001600160a01b0319169055611189816147ee565b60085460ff16156117345760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e18565b6145e2614594565b6008805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586144363390565b805f036146215750565b600b54819015614676575f600a54600b548461463d9190614f5e565b6146479190614f75565b9050801561467457600f546146679030906001600160a01b031683614453565b6146718183614ea3565b91505b505b600c54156146c9575f600a54600c54846146909190614f5e565b61469a9190614f75565b905080156146c7576011546146ba9030906001600160a01b031683614453565b6146c48183614ea3565b91505b505b600d541561471c575f600a54600d54846146e39190614f5e565b6146ed9190614f75565b9050801561471a5760105461470d9030906001600160a01b031683614453565b6147178183614ea3565b91505b505b8015610ef757600e541561473457610ef7308261483f565b601254610ef79030906001600160a01b031683614453565b6147568282612dbb565b610ef7576147638161496f565b61476e836020614981565b60405160200161477f92919061507b565b60408051601f198184030181529082905262461bcd60e51b8252610e1891600401614b45565b60085460ff166117345760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e18565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b03821661489f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610e18565b6001600160a01b0382165f90815260208190526040902054818110156149125760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610e18565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6060610d256001600160a01b03831660145b60605f61498f836002614f5e565b61499a906002614eb6565b67ffffffffffffffff8111156149b2576149b26150d9565b6040519080825280601f01601f1916602001820160405280156149dc576020820181803683370190505b509050600360fc1b815f815181106149f6576149f6614e44565b60200101906001600160f81b03191690815f1a905350600f60fb1b81600181518110614a2457614a24614e44565b60200101906001600160f81b03191690815f1a9053505f614a46846002614f5e565b614a51906001614eb6565b90505b6001811115614ac8576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614a8557614a85614e44565b1a60f81b828281518110614a9b57614a9b614e44565b60200101906001600160f81b03191690815f1a90535060049490941c93614ac1816150ed565b9050614a54565b508315614b175760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610e18565b9392505050565b5f60208284031215614b2e575f5ffd5b81356001600160e01b031981168114614b17575f5ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114613520575f5ffd5b5f5f60408385031215614ba1575f5ffd5b614baa83614b7a565b946020939093013593505050565b5f5f60408385031215614bc9575f5ffd5b614bd283614b7a565b915060208301358015158114614be6575f5ffd5b809150509250929050565b602080825282518282018190525f918401906040840190835b81811015614c315783516001600160a01b0316835260209384019390920191600101614c0a565b509095945050505050565b5f60208284031215614c4c575f5ffd5b614b1782614b7a565b5f5f5f60608486031215614c67575f5ffd5b614c7084614b7a565b9250614c7e60208501614b7a565b929592945050506040919091013590565b5f60208284031215614c9f575f5ffd5b5035919050565b5f5f60408385031215614cb7575f5ffd5b82359150614cc760208401614b7a565b90509250929050565b5f5f5f60608486031215614ce2575f5ffd5b614ceb84614b7a565b95602085013595506040909401359392505050565b5f5f83601f840112614d10575f5ffd5b50813567ffffffffffffffff811115614d27575f5ffd5b6020830191508360208260051b8501011115614d41575f5ffd5b9250929050565b5f5f5f5f60408587031215614d5b575f5ffd5b843567ffffffffffffffff811115614d71575f5ffd5b614d7d87828801614d00565b909550935050602085013567ffffffffffffffff811115614d9c575f5ffd5b614da887828801614d00565b95989497509550505050565b5f5f60408385031215614dc5575f5ffd5b614dce83614b7a565b9150614cc760208401614b7a565b600181811c90821680614df057607f821691505b602082108103614e0e57634e487b7160e01b5f52602260045260245ffd5b50919050565b602080825260169082015275092dcecc2d8d2c840e6c6d0cac8ead8ca40d2dcc8caf60531b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b6020808252601a908201527f4e6f206163746976652076657374696e67207363686564756c65000000000000604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610d2557610d25614e8f565b80820180821115610d2557610d25614e8f565b6020808252601a908201527f436f6d706f6e656e747320657863656564207461782072617465000000000000604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b6020808252818101527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604082015260600190565b8082028115828204841417610d2557610d25614e8f565b5f82614f8f57634e487b7160e01b5f52601260045260245ffd5b500490565b602080825260169082015275496e76616c69642077616c6c6574206164647265737360501b604082015260600190565b5f60018201614fd557614fd5614e8f565b5060010190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b5f81518060208401855e5f93019283525090919050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f6150ac6017830185615064565b7001034b99036b4b9b9b4b733903937b6329607d1b81526150d06011820185615064565b95945050505050565b634e487b7160e01b5f52604160045260245ffd5b5f816150fb576150fb614e8f565b505f19019056fe2ccf90dd7c30b80a460e25097b3c5ef613343f69ad6b2cfd3cfb644af593ca0ba2646970667358221220138359922dceabe5dd9dd1110cc852884aa60666f863717570de2eb733165efc64736f6c634300081e0033000000000000000000000000478b3a3697176e2bdd396ba3aef886d78c8419120000000000000000000000005120106e041c756526b08b82452a6feea2a368f8000000000000000000000000f5e7ff01a29aaeb04ebbf2d416bf218a92fbd091

Deployed Bytecode

0x608060405234801561000f575f5ffd5b5060043610610514575f3560e01c80637c791a28116102a5578063aa741bec1161016c578063cdd712da116100d5578063e30c39781161008f578063e30c397814610c10578063ec81b7b514610c21578063f023f57314610c5a578063f2fde38b14610c6d578063fbc10c5514610c80578063fdb20ccb14610c93575f5ffd5b8063cdd712da14610b85578063d12e776c14610b8d578063d547741f14610bc4578063d5a73fdd14610bd7578063dd62ed3e14610bea578063e24de5cf14610bfd575f5ffd5b8063b3daa65211610126578063b3daa65214610b20578063b65d08b014610b2a578063ba87a7c914610b33578063bed9985014610b47578063c04a541414610b50578063cb4ca63114610b63575f5ffd5b8063aa741bec14610ab9578063aacebbe314610acc578063ab4196b214610adf578063ad60572914610af2578063ae8f84a614610afa578063aef3d38614610b0d575f5ffd5b806391d148541161020e578063a217fddf116101c8578063a217fddf14610a67578063a457c2d714610a6e578063a51c9ace14610a81578063a5a1f92814610a8a578063a779d08014610a9d578063a9059cbb14610aa6575f5ffd5b806391d14854146109c0578063929066f5146109d3578063929ec537146109f557806395058acc14610a0857806395d89b4114610a1b5780639f82906314610a23575f5ffd5b80638a857bc11161025f5780638a857bc1146109645780638c0b5e22146109775780638cbc6cbe146109805780638da5cb5b146109935780638fa81732146109a4578063902d55a5146109ac575f5ffd5b80637c791a28146108fd578063809d458d1461090657806381e21e051461091957806382b17be014610921578063838a676f146109535780638456cb591461095c575f5ffd5b8063419544a0116103e95780636303516c1161035257806370a082311161030c57806370a0823114610894578063715018a6146108a757806371dd7497146108af57806375f0a874146108da57806378d10f44146108ed57806379ba5097146108f5575f5ffd5b80636303516c14610805578063640e7aef14610818578063658c27a91461082b57806369ec8e9c1461084d5780636aa22091146108785780636c24fc751461088b575f5ffd5b8063572a1c96116103a3578063572a1c961461075c57806358615c1b1461076f5780635b3317a8146107825780635c975abb1461078a5780636152d848146107955780636256d181146107f2575f5ffd5b8063419544a0146106f4578063420d4a021461070757806345f7f2491461071a5780634626402b14610723578063521dbf651461073657806354d0c09214610749575f5ffd5b80632654cccd1161048b578063343706a411610445578063343706a41461067557806335c1d3491461068857806336568abe146106b357806339509351146106c65780633de17434146106d95780633f4ba83a146106ec575f5ffd5b80632654cccd146106125780632b7887871461061a5780632f2ff15d1461062d578063311ae7ec14610640578063313ce56714610653578063336ac67314610662575f5ffd5b806318d49861116104dc57806318d498611461058f578063195ec9ee146105a257806322b54d39146105b757806323b872dd146105ca578063248a9ca3146105dd57806325ad3198146105ff575f5ffd5b806301ffc9a71461051857806306fdde0314610540578063095ea7b3146105555780630be41d151461056857806318160ddd1461057d575b5f5ffd5b61052b610526366004614b1e565b610cf5565b60405190151581526020015b60405180910390f35b610548610d2b565b6040516105379190614b45565b61052b610563366004614b90565b610dbb565b61057b610576366004614b90565b610dd2565b005b6002545b604051908152602001610537565b61057b61059d366004614bb8565b610efb565b6105aa610f66565b6040516105379190614bf1565b61057b6105c5366004614c3c565b610fc5565b61052b6105d8366004614c55565b61118c565b6105816105eb366004614c8f565b5f9081526009602052604090206001015490565b61057b61060d366004614c8f565b6111af565b61057b61123c565b61057b610628366004614c8f565b611288565b61057b61063b366004614ca6565b61130e565b61057b61064e366004614c3c565b611337565b60405160128152602001610537565b61057b610670366004614bb8565b6113c9565b61057b610683366004614b90565b61142c565b61069b610696366004614c8f565b6115ac565b6040516001600160a01b039091168152602001610537565b61057b6106c1366004614ca6565b6115d4565b61052b6106d4366004614b90565b61164e565b6105816106e7366004614c3c565b61166f565b61057b611724565b61057b610702366004614b90565b611736565b610581610715366004614c3c565b611c22565b610581601a5481565b60125461069b906001600160a01b031681565b61057b610744366004614b90565b611c7c565b61057b610757366004614cd0565b611d3e565b61057b61076a366004614c8f565b611f19565b61057b61077d366004614c8f565b611f9e565b610581603c81565b60085460ff1661052b565b6107a86107a3366004614b90565b61206f565b60408051988952602089019790975295870194909452606086019290925215156080850152151560a08401526001600160a01b031660c0830152151560e082015261010001610537565b61057b610800366004614c8f565b6120df565b600f5461069b906001600160a01b031681565b61052b610826366004614c3c565b61217b565b61052b610839366004614c3c565b60146020525f908152604090205460ff1681565b61052b61085b366004614c3c565b6001600160a01b03165f9081526013602052604090205460ff1690565b61057b610886366004614d48565b61223e565b610581600b5481565b6105816108a2366004614c3c565b6129a4565b61057b6129c1565b61052b6108bd366004614c3c565b6001600160a01b03165f9081526014602052604090205460ff1690565b60105461069b906001600160a01b031681565b610581604681565b61057b6129d2565b610581600c5481565b61057b610914366004614c3c565b612a49565b61057b612ac5565b610929612add565b6040805195865260208601949094529284019190915260608301521515608082015260a001610537565b610581600d5481565b61057b612b14565b6105816be8a5010cf2a411214000000081565b61058160155481565b61057b61098e366004614cd0565b612b24565b6005546001600160a01b031661069b565b610581606481565b6105816c02863c1f5cdae42f954000000081565b61052b6109ce366004614ca6565b612dbb565b61052b6109e1366004614c3c565b60196020525f908152604090205460ff1681565b610581610a03366004614c3c565b612de5565b61057b610a16366004614b90565b612eb3565b610548612f9f565b610a36610a31366004614c3c565b612fae565b60408051968752602087019590955293850192909252606084015215156080830152151560a082015260c001610537565b6105815f81565b61052b610a7c366004614b90565b61305f565b6105816103e881565b61057b610a98366004614c3c565b6130d9565b610581601b5481565b61052b610ab4366004614b90565b613168565b61057b610ac7366004614c3c565b613175565b61057b610ada366004614c3c565b613431565b610581610aed366004614c3c565b6134ad565b601854610581565b61057b610b08366004614b90565b613525565b61052b610b1b366004614c3c565b6137c0565b61058162ed4e0081565b610581600a5481565b6105815f5160206151035f395f51905f5281565b610581600e5481565b60115461069b906001600160a01b031681565b61052b610b71366004614c3c565b60136020525f908152604090205460ff1681565b610581600c81565b600a54600b54600c54600d54600e54604080519586526020860194909452928401919091526060830152608082015260a001610537565b61057b610bd2366004614ca6565b6137d8565b610581610be5366004614c3c565b6137fc565b610581610bf8366004614db4565b613887565b61057b610c0b366004614c8f565b6138b1565b6006546001600160a01b031661069b565b610c34610c2f366004614d48565b613937565b604080519485526020850193909352901515918301919091526060820152608001610537565b61057b610c68366004614c3c565b613a46565b61057b610c7b366004614c3c565b613ac2565b61057b610c8e366004614c3c565b613b33565b6107a8610ca1366004614c3c565b60166020525f9081526040902080546001820154600283015460038401546004909401549293919290919060ff8082169161010081048216916001600160a01b036201000083041691600160b01b90041688565b5f6001600160e01b03198216637965db0b60e01b1480610d2557506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060038054610d3a90614ddc565b80601f0160208091040260200160405190810160405280929190818152602001828054610d6690614ddc565b8015610db15780601f10610d8857610100808354040283529160200191610db1565b820191905f5260205f20905b815481529060010190602001808311610d9457829003601f168201915b5050505050905090565b5f33610dc8818585613baf565b5060019392505050565b610dda613cd2565b610de2613d2c565b6001600160a01b0382165f908152601760205260409020548110610e215760405162461bcd60e51b8152600401610e1890614e14565b60405180910390fd5b6001600160a01b0382165f908152601760205260408120805483908110610e4a57610e4a614e44565b5f9182526020909120600590910201600481015490915060ff16610e805760405162461bcd60e51b8152600401610e1890614e58565b60048101805460ff610100808304821615810261ff00199093169290921792839055604080519290930416151581524260208201526001600160a01b038516917fc9031c29f273e1fcfe9c1bcaa668b10bc343a9e84ad019f7dc3665ec8a0994d191015b60405180910390a250610ef76001600755565b5050565b610f03613cd2565b6001600160a01b0382165f81815260136020908152604091829020805460ff19168515159081179091558251938452908301527f057dc60ecf6df48e0f4af40ef0f88074d41e0ce54a1fef20925cd23c6de0386091015b60405180910390a15050565b60606018805480602002602001604051908101604052809291908181526020018280548015610db157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610f9e575050505050905090565b610fcd613cd2565b610fd5613d2c565b5f610fdf82613d85565b50905080610fff5760405162461bcd60e51b8152600401610e1890614e58565b6001600160a01b0382165f90815260176020526040812090805b82548110156110d3575f83828154811061103557611035614e44565b5f9182526020909120600590910201600481015490915060ff1661105957506110cb565b5f6110648242613dc7565b90505f8260010154821161107c57826001015461107e565b815b90505f81845f015411611091575f61109e565b835461109e908390614ea3565b905080156110c657835460018501556110b78187614eb6565b60048501805460ff1916905595505b505050505b600101611019565b505f81116111235760405162461bcd60e51b815260206004820152601860248201527f4e6f20746f6b656e73206c65667420746f20756e6c6f636b00000000000000006044820152606401610e18565b80601b5f8282546111349190614eb6565b9091555050604080518281524260208201526001600160a01b038616917f99b50e15cf191f04bfbfd29e284810ecd067636b6c33cbf6134d6d65beb5a6d9910160405180910390a25050506111896001600755565b50565b5f33611199858285613fce565b6111a4858585614046565b506001949350505050565b6111b7613cd2565b600a54600e54600d5483600b546111ce9190614eb6565b6111d89190614eb6565b6111e29190614eb6565b11156112005760405162461bcd60e51b8152600401610e1890614ec9565b600c8190556040518181527f5e10fd5ddf113b5355f7a23f3d729f6e938dd4f13642c82f11469afa02f8548a906020015b60405180910390a150565b611244613cd2565b6018545f5b81811015610ef7576112806018828154811061126757611267614e44565b5f918252602090912001546001600160a01b0316613175565b600101611249565b611290613cd2565b600a5481600d54600c54600b546112a79190614eb6565b6112b19190614eb6565b6112bb9190614eb6565b11156112d95760405162461bcd60e51b8152600401610e1890614ec9565b600e8190556040518181527f47863b595116a31383855975a4078913dce7881e717b75a06ced2db5d534ff7890602001611231565b5f828152600960205260409020600101546113288161430c565b6113328383614316565b505050565b61133f613cd2565b6001600160a01b0381166113655760405162461bcd60e51b8152600401610e1890614f00565b61137c5f5160206151035f395f51905f5282614316565b6001600160a01b0381165f81815260136020526040808220805460ff19166001179055513392917fbefa07af2dfa4c1c71661acd889424e95a2f805bdbf833573f60374e52d7130691a350565b6113d1613cd2565b6001600160a01b0382165f81815260146020908152604091829020805460ff19168515159081179091558251938452908301527f4fde41d38f7a4818cef6b418d1048204bae25e6104e02ddf7f89c3c233b3eda99101610f5a565b611434613cd2565b61143c613d2c565b6001600160a01b0382165f9081526017602052604090205481106114725760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0382165f90815260176020526040812080548390811061149b5761149b614e44565b5f9182526020909120600590910201600481015490915060ff166114d15760405162461bcd60e51b8152600401610e1890614e58565b425f6114dd8383613dc7565b90505f836001015482116114f55783600101546114f7565b815b90505f81855f01541161150a575f611517565b8454611517908390614ea3565b60048601805460ff60ff60b01b011916600160b01b1790555f6002870181905560038701819055601a80549293508392909190611555908490614ea3565b9091555050604080518281524260208201526001600160a01b038916917f7ccdce830ffcfd4ae5baac3fbca1ba04c1135db945a98e65924c2ad7bd1a4422910160405180910390a25050505050610ef76001600755565b601881815481106115bb575f80fd5b5f918252602090912001546001600160a01b0316905081565b6001600160a01b03811633146116445760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610e18565b610ef7828261439b565b5f33610dc88185856116608383613887565b61166a9190614eb6565b613baf565b6001600160a01b0381165f9081526019602052604081205460ff1661169557505f919050565b6001600160a01b0382165f90815260176020526040812090805b825481101561171c578281815481106116ca576116ca614e44565b5f91825260209091206004600590920201015460ff1615611714578281815481106116f7576116f7614e44565b905f5260205f2090600502015f0154826117119190614eb6565b91505b6001016116af565b509392505050565b61172c613cd2565b611734614401565b565b5f5160206151035f395f51905f5261174d8161430c565b611755613d2c565b6001600160a01b0383166117a25760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642075736572206164647265737360601b6044820152606401610e18565b5f82116117c15760405162461bcd60e51b8152600401610e1890614f29565b816117cb336129a4565b10156118195760405162461bcd60e51b815260206004820152601f60248201527f496e73756666696369656e7420746f6b656e7320666f722076657374696e67006044820152606401610e18565b611824338484614046565b5f5f600a541180156118455750335f9081526013602052604090205460ff16155b801561186957506001600160a01b0384165f9081526013602052604090205460ff16155b90505f81611877578361189c565b6103e8600a54856118889190614f5e565b6118929190614f75565b61189c9085614ea3565b604080518281524260208201529192506001600160a01b038716917f95f5297f9f827597da7117f9efc0ab78db5461cff01c5f842aac80d292df34e0910160405180910390a2425f6118f28263096c9900614eb6565b90505f6040518061010001604052808581526020015f8152602001848152602001838152602001600115158152602001600115158152602001336001600160a01b031681526020015f151581525090508060165f8a6001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f01556020820151816001015560408201518160020155606082015181600301556080820151816004015f6101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548160ff02191690831515021790555060c08201518160040160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160040160166101000a81548160ff02191690831515021790555090505060175f896001600160a01b03166001600160a01b031681526020019081526020015f2081908060018154018082558091505060019003905f5260205f2090600502015f909190919091505f820151815f01556020820151816001015560408201518160020155606082015181600301556080820151816004015f6101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548160ff02191690831515021790555060c08201518160040160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160040160166101000a81548160ff021916908315150217905550505060195f896001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff16611bb0576018805460018082019092557fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e0180546001600160a01b0319166001600160a01b038b169081179091555f908152601960205260409020805460ff191690911790555b83601a5f828254611bc19190614eb6565b909155505060408051858152602081018590529081018390526001600160a01b038916907f892f1a841b10e4b041cc41d8cc47c6a6049f1ff5fa272ddf47a0aa5ad8f59d13906060015b60405180910390a250505050506113326001600755565b6001600160a01b0381165f90815260176020526040812081805b825481101561171c57828181548110611c5757611c57614e44565b905f5260205f2090600502016001015482611c729190614eb6565b9150600101611c3c565b611c84613cd2565b611c8c613d2c565b6001600160a01b038216611cb25760405162461bcd60e51b8152600401610e1890614f00565b5f8111611cd15760405162461bcd60e51b8152600401610e1890614f29565b80611cdb306129a4565b1015611d295760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606401610e18565b611d34308383614453565b610ef76001600755565b611d46613cd2565b611d4e613d2c565b6001600160a01b0383165f908152601760205260409020548210611d845760405162461bcd60e51b8152600401610e1890614e14565b5f8111611da35760405162461bcd60e51b8152600401610e1890614f29565b6001600160a01b0383165f908152601760205260408120805484908110611dcc57611dcc614e44565b5f9182526020909120600590910201600481015490915060ff16611e025760405162461bcd60e51b8152600401610e1890614e58565b425f611e0e8383613dc7565b90505f83600101548211611e26578360010154611e28565b815b90505f81855f015411611e3b575f611e48565b8454611e48908390614ea3565b905080861115611ea95760405162461bcd60e51b815260206004820152602660248201527f416d6f756e7420657863656564732072656d61696e696e67206c6f636b656420604482015265746f6b656e7360d01b6064820152608401610e18565b85856001015f828254611ebc9190614eb6565b9250508190555085601b5f828254611ed49190614eb6565b9091555050604080518781524260208201526001600160a01b038a16917f5f2c0ba2f60ed002c855ce66ef5bc7c00a85b717d286d415a2bcb5f8ed55796b9101611c0b565b611f21613cd2565b600a54600e54600d54600c54611f379085614eb6565b611f419190614eb6565b611f4b9190614eb6565b1115611f695760405162461bcd60e51b8152600401610e1890614ec9565b600b8190556040518181527f03d5690a884c4427453657817210296ad15540b3dd7e88a20adba9fdfe04f74f90602001611231565b611fa6613cd2565b6064811115611feb5760405162461bcd60e51b81526020600482015260116024820152700a8c2f040e4c2e8ca40e8dede40d0d2ced607b1b6044820152606401610e18565b801561203a5780600e54600d54600c54600b546120089190614eb6565b6120129190614eb6565b61201c9190614eb6565b111561203a5760405162461bcd60e51b8152600401610e1890614ec9565b600a8190556040518181527fe9b79e1a6c2dc43b4c0c6ff01ce9e3332d810e482270f464c0a21ad6c5fc6de390602001611231565b6017602052815f5260405f208181548110612088575f80fd5b5f91825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff8082169161010081048216916001600160a01b036201000083041691600160b01b90041688565b6120e7613cd2565b5f81116121465760405162461bcd60e51b815260206004820152602760248201527f4d617820747820616d6f756e74206d7573742062652067726561746572207468604482015266616e207a65726f60c81b6064820152608401610e18565b60158190556040518181527f947f344d56e1e8c70dc492fb94c4ddddd490c016aab685f5e7e47b2e85cb44cf90602001611231565b6001600160a01b0381165f908152601760205260408120805482036121a257505f92915050565b5f5b8154811015610dc8575f8282815481106121c0576121c0614e44565b5f9182526020909120600590910201600481015490915060ff166121e45750612236565b6003810154429081106121f8575050612236565b816002015481101561220f57505f95945050505050565b5f61221a8383613dc7565b835490915081101561223257505f9695505050505050565b5050505b6001016121a4565b5f5160206151035f395f51905f526122558161430c565b61225d613d2c565b8382146122a55760405162461bcd60e51b8152602060048201526016602482015275082e4e4c2f2e640d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606401610e18565b836122e15760405162461bcd60e51b815260206004820152600c60248201526b456d7074792061727261797360a01b6044820152606401610e18565b5f805b83811015612376575f8787838181106122ff576122ff614e44565b90506020020160208101906123149190614c3c565b6001600160a01b03161415801561234257505f85858381811061233957612339614e44565b90506020020135115b1561236e5784848281811061235957612359614e44565b905060200201358261236b9190614eb6565b91505b6001016122e4565b5080612381336129a4565b10156123db5760405162461bcd60e51b8152602060048201526024808201527f496e73756666696369656e7420746f6b656e7320666f722062756c6b2076657360448201526374696e6760e01b6064820152608401610e18565b425f6123eb8263096c9900614eb6565b90505f5b8781101561298f575f89898381811061240a5761240a614e44565b905060200201602081019061241f9190614c3c565b6001600160a01b03161415801561244d57505f87878381811061244457612444614e44565b90506020020135115b156129875761249b338a8a8481811061246857612468614e44565b905060200201602081019061247d9190614c3c565b89898581811061248f5761248f614e44565b90506020020135614046565b5f5f600a541180156124bc5750335f9081526013602052604090205460ff16155b801561250b575060135f8b8b858181106124d8576124d8614e44565b90506020020160208101906124ed9190614c3c565b6001600160a01b0316815260208101919091526040015f205460ff16155b90505f816125315788888481811061252557612525614e44565b90506020020135612587565b6103e8600a548a8a8681811061254957612549614e44565b9050602002013561255a9190614f5e565b6125649190614f75565b89898581811061257657612576614e44565b905060200201356125879190614ea3565b90508a8a8481811061259b5761259b614e44565b90506020020160208101906125b09190614c3c565b6001600160a01b03167f95f5297f9f827597da7117f9efc0ab78db5461cff01c5f842aac80d292df34e082426040516125f3929190918252602082015260400190565b60405180910390a260408051610100810182528281525f602082018190529181018790526060810186905260016080820181905260a08201523360c082015260e081018290529081906016908e8e8881811061265157612651614e44565b90506020020160208101906126669190614c3c565b6001600160a01b03908116825260208083019390935260409182015f908120855181559385015160018501559184015160028401556060840151600384015560808401516004909301805460a086015160c087015160e09097015161ffff1990921695151561ff00191695909517610100951515959095029490941762010000600160b81b03191662010000959092169490940260ff60b01b191617600160b01b92151592909202919091179091556017908d8d8781811061272a5761272a614e44565b905060200201602081019061273f9190614c3c565b6001600160a01b03908116825260208083019390935260409182015f908120805460018181018355918352858320875160059092020190815594860151908501559184015160028401556060840151600384015560808401516004909301805460a086015160c087015160e08801511515600160b01b0260ff60b01b199190951662010000021662010000600160b81b03199115156101000261ff00199715159790971661ffff1990931692909217959095179490941693909317179091556019908d8d8781811061281357612813614e44565b90506020020160208101906128289190614c3c565b6001600160a01b0316815260208101919091526040015f205460ff166128f75760188c8c8681811061285c5761285c614e44565b90506020020160208101906128719190614c3c565b8154600180820184555f9384526020842090910180546001600160a01b0319166001600160a01b039390931692909217909155906019908e8e888181106128ba576128ba614e44565b90506020020160208101906128cf9190614c3c565b6001600160a01b0316815260208101919091526040015f20805460ff19169115159190911790555b81601a5f8282546129089190614eb6565b909155508c90508b8581811061292057612920614e44565b90506020020160208101906129359190614c3c565b60408051848152602081018990529081018790526001600160a01b0391909116907f892f1a841b10e4b041cc41d8cc47c6a6049f1ff5fa272ddf47a0aa5ad8f59d139060600160405180910390a25050505b6001016123ef565b5050505061299d6001600755565b5050505050565b6001600160a01b0381165f90815260208190526040812054610d25565b6129c9613cd2565b6117345f61457b565b60065433906001600160a01b03168114612a405760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610e18565b6111898161457b565b612a51613cd2565b6001600160a01b038116612a775760405162461bcd60e51b8152600401610e1890614f94565b601280546001600160a01b0319166001600160a01b0383169081179091556040519081527f97c79b3848e51f57983ac89e4403452655c8d83ceba8199011de63a74f60d1a790602001611231565b612acd613cd2565b612ad5614594565b6117346129c1565b5f5f5f5f5f601880549050601a54601b54601b54601a54612afe9190614ea3565b6018549399929850909650945090151592509050565b612b1c613cd2565b6117346145da565b612b2c613d2c565b6001600160a01b0383165f908152601760205260409020548210612b625760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0383165f908152601760205260408120805484908110612b8b57612b8b614e44565b5f9182526020909120600590910201600481015490915060ff16612bc15760405162461bcd60e51b8152600401610e1890614e58565b60048101546201000090046001600160a01b03163314612c1b5760405162461bcd60e51b815260206004820152601560248201527427b7363c9039b1b432b23ab6329031b932b0ba37b960591b6044820152606401610e18565b425f612c278383613dc7565b90505f81846001015411612c3b5781612c41565b83600101545b905080851015612c935760405162461bcd60e51b815260206004820152601b60248201527f4e657720616d6f756e74206c657373207468616e2076657374656400000000006044820152606401610e18565b835480861115612d52575f612ca88288614ea3565b905080612cb4336129a4565b1015612d025760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420746f6b656e7320666f7220696e6372656173656044820152606401610e18565b612d0d338a83614046565b604080518281524260208201526001600160a01b038b16917f95f5297f9f827597da7117f9efc0ab78db5461cff01c5f842aac80d292df34e0910160405180910390a2505b858555601a548690612d65908390614ea3565b612d6f9190614eb6565b601a55612d7b88613175565b604080518781524260208201526001600160a01b038a16917fcb7620a89fe7effd1ec7a600cae454314b7a51b26f215d7ad59f5070fad46dde9101611c0b565b5f9182526009602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6001600160a01b0381165f90815260176020526040812081805b825481101561171c575f838281548110612e1b57612e1b614e44565b5f9182526020909120600590910201600481015490915060ff16612e3f5750612eab565b600381015442908110612e53575050612eab565b5f612e5e8383613dc7565b60018401549091505f818311612e745781612e76565b825b90505f81865f015411612e89575f612e96565b8554612e96908390614ea3565b9050612ea28189614eb6565b97505050505050505b600101612dff565b612ebb613cd2565b612ec3613d2c565b6001600160a01b0382165f908152601760205260409020548110612ef95760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0382165f908152601760205260408120805483908110612f2257612f22614e44565b5f9182526020909120600590910201600481015490915060ff16612f585760405162461bcd60e51b8152600401610e1890614e58565b60048101805460ff191690556040514281526001600160a01b038416907f27afda27f49489e1414b933acd435beef4ac058ffa59989c360ac892def427fc90602001610ee4565b606060048054610d3a90614ddc565b6001600160a01b0381165f908152601760205260408120805482918291829182918291908203612ff0575f5f5f5f5f5f96509650965096509650965050613056565b80545f90829061300290600190614ea3565b8154811061301257613012614e44565b5f91825260209091206005909102018054600182015460028301546003840154600490940154929b50909950975090955060ff808216955061010090910416925050505b91939550919395565b5f338161306c8286613887565b9050838110156130cc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610e18565b6111a48286868403613baf565b6130e1613cd2565b6001600160a01b0381166131075760405162461bcd60e51b8152600401610e1890614f00565b61311e5f5160206151035f395f51905f528261439b565b6001600160a01b0381165f81815260136020526040808220805460ff19169055513392917f827af9c874807d9353cf2b4c17319dba2ff27651355b0e78fecc29f4e386ba9691a350565b5f33610dc8818585614046565b6001600160a01b0381165f908152601760205260408120905b8154811015611332575f8282815481106131aa576131aa614e44565b5f9182526020909120600590910201600481015490915060ff1615806131d257506002810154155b156131dd5750613429565b6003810154429081106132c85781546001830154101561327057600182015482545f9161320991614ea3565b83546001850155601b805491925082915f90613226908490614eb6565b9091555050604080518281524260208201526001600160a01b038816917f89882ad382a3742d4db24e4dabc5000c5852aed762904db28442e4e1630a1d07910160405180910390a2505b60048201805460ff191690558154604080519182524260208301526001600160a01b038716917f2f2bd35e8c85fab03ec786f38a3e9424e1c4823c8a5cbd23a32664dd27dfdd22910160405180910390a25050613429565b5f6132d38383613dc7565b9050826001015481111561335c575f8360010154826132f29190614ea3565b905081846001018190555080601b5f82825461330e9190614eb6565b9091555050604080518281524260208201526001600160a01b038916917f89882ad382a3742d4db24e4dabc5000c5852aed762904db28442e4e1630a1d07910160405180910390a2506133b9565b82600101548110156133b9576001830154604080519182526020820183905242908201526001600160a01b038716907f102441b567edf9782e9aa2ce227915f2e7aa6d6203be9970bc6dbbf655f488d79060600160405180910390a25b825481108015906133ce5750600483015460ff165b156134255760048301805460ff191690558254604080519182524260208301526001600160a01b038816917f2f2bd35e8c85fab03ec786f38a3e9424e1c4823c8a5cbd23a32664dd27dfdd22910160405180910390a25b5050505b60010161318e565b613439613cd2565b6001600160a01b03811661345f5760405162461bcd60e51b8152600401610e1890614f94565b601080546001600160a01b0319166001600160a01b0383169081179091556040519081527fbf86feedee5b30c30a8243bd21deebb704d141478d39b1be04fe5ee739f214e790602001611231565b6001600160a01b0381165f9081526019602052604081205460ff1615613503576001600160a01b0382165f90815260208190526040812054906134ef84612de5565b90506134fb8183614ea3565b949350505050565b6001600160a01b0382165f90815260208190526040902054610d25565b919050565b61352d613cd2565b613535613d2c565b6001600160a01b0382165f90815260176020526040902054811061356b5760405162461bcd60e51b8152600401610e1890614e14565b6001600160a01b0382165f90815260176020526040812080548390811061359457613594614e44565b905f5260205f20906005020190508060040160169054906101000a900460ff16156136015760405162461bcd60e51b815260206004820152601a60248201527f56657374696e67207363686564756c652063616e63656c6c65640000000000006044820152606401610e18565b600481015460ff16156136615760405162461bcd60e51b815260206004820152602260248201527f56657374696e67207363686564756c6520697320616c72656164792061637469604482015261766560f01b6064820152608401610e18565b80600201545f036136b45760405162461bcd60e51b815260206004820152601a60248201527f4e6f2076657374696e67207363686564756c65206578697374730000000000006044820152606401610e18565b5f6136bf8242613dc7565b90505f818360010154116136d357816136d9565b82600101545b90505f81845f0154116136ec575f6136f9565b83546136f9908390614ea3565b905080613705876134ad565b101561375e5760405162461bcd60e51b815260206004820152602260248201527f496e73756666696369656e742062616c616e636520746f207265616374697661604482015261746560f01b6064820152608401610e18565b60048401805460ff191660011790556040516001600160a01b038716907f3bfe7418887a68023ea2000b535ae874d807ced1c0e7b6e904791012bdda7165906137aa9042815260200190565b60405180910390a250505050610ef76001600755565b5f610d255f5160206151035f395f51905f5283612dbb565b5f828152600960205260409020600101546137f28161430c565b611332838361439b565b6001600160a01b0381165f90815260176020526040812081805b825481101561171c575f83828154811061383257613832614e44565b5f9182526020909120600590910201600481015490915060ff16158061385a57506002810154155b15613865575061387f565b426138708282613dc7565b61387a9085614eb6565b935050505b600101613816565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6138b9613cd2565b600a54600e5482600c54600b546138d09190614eb6565b6138da9190614eb6565b6138e49190614eb6565b11156139025760405162461bcd60e51b8152600401610e1890614ec9565b600d8190556040518181527fe5493206f305f48f22963f38bf60fcb4685e3af5843619da148412268d2f0a7090602001611231565b5f8080808685146139835760405162461bcd60e51b8152602060048201526016602482015275082e4e4c2f2e640d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606401610e18565b505f925082805b85811015613a29575f8989838181106139a5576139a5614e44565b90506020020160208101906139ba9190614c3c565b6001600160a01b0316141580156139e857505f8787838181106139df576139df614e44565b90506020020135115b15613a21578686828181106139ff576139ff614e44565b9050602002013585613a119190614eb6565b945081613a1d81614fc4565b9250505b60010161398a565b50613a33336129a4565b9250838310159150945094509450949050565b613a4e613cd2565b6001600160a01b038116613a745760405162461bcd60e51b8152600401610e1890614f94565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527f59fd076cdcd0c12d650e7d16898047308777be9d03b00a2907a56cb113412be590602001611231565b613aca613cd2565b600680546001600160a01b0383166001600160a01b03199091168117909155613afb6005546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b613b3b613cd2565b6001600160a01b038116613b615760405162461bcd60e51b8152600401610e1890614f94565b600f80546001600160a01b0319166001600160a01b0383169081179091556040519081527f71bcdff234e981b4f1f8acf4fbf6c9aab4fb20bdc744ba24715786dbadcee1aa90602001611231565b6001600160a01b038316613c115760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610e18565b6001600160a01b038216613c725760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610e18565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6005546001600160a01b031633146117345760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e18565b600260075403613d7e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e18565b6002600755565b6001600160a01b0381165f908152601760205260408120548190808203613db157505f93849350915050565b6001613dbd8183614ea3565b9250925050915091565b5f8260020154821015613ddb57505f610d25565b82600301548210613dee57508154610d25565b5f836002015483613dff9190614ea3565b90505f613e0f62278d0083614f75565b90506007811015613e24575f92505050610d25565b5f8060078310613e3c5780613e3881614fc4565b9150505b600a8310613e525780613e4e81614fc4565b9150505b600d8310613e685780613e6481614fc4565b9150505b60108310613e7e5780613e7a81614fc4565b9150505b60138310613e945780613e9081614fc4565b9150505b5f6103e8600c895f0154613ea89190614f5e565b613eb29190614f75565b9050613ebe8282614f5e565b613ec89084614eb6565b925060168410613f3f575f60165b60318111613f0557808610613ef35781613eef81614fc4565b9250505b613efe600382614eb6565b9050613ed6565b505f6103e860468b5f0154613f1a9190614f5e565b613f249190614f75565b9050613f308282614f5e565b613f3a9086614eb6565b945050505b60348410613fb4575f60345b603d8111613f7a57808610613f685781613f6481614fc4565b9250505b613f73600382614eb6565b9050613f4b565b505f6103e8603c8b5f0154613f8f9190614f5e565b613f999190614f75565b9050613fa58282614f5e565b613faf9086614eb6565b945050505b8754831115613fc257875492505b50909695505050505050565b5f613fd98484613887565b90505f19811461404057818110156140335760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610e18565b6140408484848403613baf565b50505050565b61404e614594565b6001600160a01b0383166140745760405162461bcd60e51b8152600401610e1890614fdc565b6001600160a01b03821661409a5760405162461bcd60e51b8152600401610e1890615021565b5f81116140fb5760405162461bcd60e51b815260206004820152602960248201527f5472616e7366657220616d6f756e74206d7573742062652067726561746572206044820152687468616e207a65726f60b81b6064820152608401610e18565b6001600160a01b0383165f9081526019602052604090205460ff16156141245761412483613175565b6001600160a01b0382165f9081526019602052604090205460ff161561414d5761414d82613175565b5f614157846134ad565b9050818110156141b35760405162461bcd60e51b815260206004820152602160248201527f496e73756666696369656e74207472616e7366657261626c652062616c616e636044820152606560f81b6064820152608401610e18565b6001600160a01b0384165f9081526014602052604090205460ff161580156141f357506001600160a01b0383165f9081526014602052604090205460ff16155b15614260576015548211156142605760405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657220616d6f756e742065786365656473206d6178207472616e60448201526c1cd858dd1a5bdb881b1a5b5a5d609a1b6064820152608401610e18565b600a545f901580159061428b57506001600160a01b0385165f9081526013602052604090205460ff16155b80156142af57506001600160a01b0384165f9081526013602052604090205460ff16155b156142d2576103e8600a54846142c59190614f5e565b6142cf9190614f75565b90505b5f6142dd8285614ea3565b90506142ea868683614453565b8115614304576142fb863084614453565b61430482614617565b505050505050565b611189813361474c565b6143208282612dbb565b610ef7575f8281526009602090815260408083206001600160a01b03851684529091529020805460ff191660011790556143573390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6143a58282612dbb565b15610ef7575f8281526009602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6144096147a5565b6008805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0383166144795760405162461bcd60e51b8152600401610e1890614fdc565b6001600160a01b03821661449f5760405162461bcd60e51b8152600401610e1890615021565b6001600160a01b0383165f90815260208190526040902054818110156145165760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610e18565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3614040565b600680546001600160a01b0319169055611189816147ee565b60085460ff16156117345760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e18565b6145e2614594565b6008805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586144363390565b805f036146215750565b600b54819015614676575f600a54600b548461463d9190614f5e565b6146479190614f75565b9050801561467457600f546146679030906001600160a01b031683614453565b6146718183614ea3565b91505b505b600c54156146c9575f600a54600c54846146909190614f5e565b61469a9190614f75565b905080156146c7576011546146ba9030906001600160a01b031683614453565b6146c48183614ea3565b91505b505b600d541561471c575f600a54600d54846146e39190614f5e565b6146ed9190614f75565b9050801561471a5760105461470d9030906001600160a01b031683614453565b6147178183614ea3565b91505b505b8015610ef757600e541561473457610ef7308261483f565b601254610ef79030906001600160a01b031683614453565b6147568282612dbb565b610ef7576147638161496f565b61476e836020614981565b60405160200161477f92919061507b565b60408051601f198184030181529082905262461bcd60e51b8252610e1891600401614b45565b60085460ff166117345760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e18565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b03821661489f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610e18565b6001600160a01b0382165f90815260208190526040902054818110156149125760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610e18565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6060610d256001600160a01b03831660145b60605f61498f836002614f5e565b61499a906002614eb6565b67ffffffffffffffff8111156149b2576149b26150d9565b6040519080825280601f01601f1916602001820160405280156149dc576020820181803683370190505b509050600360fc1b815f815181106149f6576149f6614e44565b60200101906001600160f81b03191690815f1a905350600f60fb1b81600181518110614a2457614a24614e44565b60200101906001600160f81b03191690815f1a9053505f614a46846002614f5e565b614a51906001614eb6565b90505b6001811115614ac8576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614a8557614a85614e44565b1a60f81b828281518110614a9b57614a9b614e44565b60200101906001600160f81b03191690815f1a90535060049490941c93614ac1816150ed565b9050614a54565b508315614b175760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610e18565b9392505050565b5f60208284031215614b2e575f5ffd5b81356001600160e01b031981168114614b17575f5ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114613520575f5ffd5b5f5f60408385031215614ba1575f5ffd5b614baa83614b7a565b946020939093013593505050565b5f5f60408385031215614bc9575f5ffd5b614bd283614b7a565b915060208301358015158114614be6575f5ffd5b809150509250929050565b602080825282518282018190525f918401906040840190835b81811015614c315783516001600160a01b0316835260209384019390920191600101614c0a565b509095945050505050565b5f60208284031215614c4c575f5ffd5b614b1782614b7a565b5f5f5f60608486031215614c67575f5ffd5b614c7084614b7a565b9250614c7e60208501614b7a565b929592945050506040919091013590565b5f60208284031215614c9f575f5ffd5b5035919050565b5f5f60408385031215614cb7575f5ffd5b82359150614cc760208401614b7a565b90509250929050565b5f5f5f60608486031215614ce2575f5ffd5b614ceb84614b7a565b95602085013595506040909401359392505050565b5f5f83601f840112614d10575f5ffd5b50813567ffffffffffffffff811115614d27575f5ffd5b6020830191508360208260051b8501011115614d41575f5ffd5b9250929050565b5f5f5f5f60408587031215614d5b575f5ffd5b843567ffffffffffffffff811115614d71575f5ffd5b614d7d87828801614d00565b909550935050602085013567ffffffffffffffff811115614d9c575f5ffd5b614da887828801614d00565b95989497509550505050565b5f5f60408385031215614dc5575f5ffd5b614dce83614b7a565b9150614cc760208401614b7a565b600181811c90821680614df057607f821691505b602082108103614e0e57634e487b7160e01b5f52602260045260245ffd5b50919050565b602080825260169082015275092dcecc2d8d2c840e6c6d0cac8ead8ca40d2dcc8caf60531b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b6020808252601a908201527f4e6f206163746976652076657374696e67207363686564756c65000000000000604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610d2557610d25614e8f565b80820180821115610d2557610d25614e8f565b6020808252601a908201527f436f6d706f6e656e747320657863656564207461782072617465000000000000604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b6020808252818101527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604082015260600190565b8082028115828204841417610d2557610d25614e8f565b5f82614f8f57634e487b7160e01b5f52601260045260245ffd5b500490565b602080825260169082015275496e76616c69642077616c6c6574206164647265737360501b604082015260600190565b5f60018201614fd557614fd5614e8f565b5060010190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b5f81518060208401855e5f93019283525090919050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f6150ac6017830185615064565b7001034b99036b4b9b9b4b733903937b6329607d1b81526150d06011820185615064565b95945050505050565b634e487b7160e01b5f52604160045260245ffd5b5f816150fb576150fb614e8f565b505f19019056fe2ccf90dd7c30b80a460e25097b3c5ef613343f69ad6b2cfd3cfb644af593ca0ba2646970667358221220138359922dceabe5dd9dd1110cc852884aa60666f863717570de2eb733165efc64736f6c634300081e0033

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

000000000000000000000000478b3a3697176e2bdd396ba3aef886d78c8419120000000000000000000000005120106e041c756526b08b82452a6feea2a368f8000000000000000000000000f5e7ff01a29aaeb04ebbf2d416bf218a92fbd091

-----Decoded View---------------
Arg [0] : _lpWallet (address): 0x478B3A3697176e2bdd396bA3AeF886d78C841912
Arg [1] : _marketingWallet (address): 0x5120106E041C756526B08b82452A6feEA2A368f8
Arg [2] : _developmentWallet (address): 0xF5E7fF01A29AaeB04EBbF2d416Bf218a92FbD091

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000478b3a3697176e2bdd396ba3aef886d78c841912
Arg [1] : 0000000000000000000000005120106e041c756526b08b82452a6feea2a368f8
Arg [2] : 000000000000000000000000f5e7ff01a29aaeb04ebbf2d416bf218a92fbd091


Deployed Bytecode Sourcemap

59168:44048:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38043:204;;;;;;:::i;:::-;;:::i;:::-;;;470:14:1;;463:22;445:41;;433:2;418:18;38043:204:0;;;;;;;;47937:100;;;:::i;:::-;;;;;;;:::i;50297:201::-;;;;;;:::i;:::-;;:::i;88063:530::-;;;;;;:::i;:::-;;:::i;:::-;;49066:108;49154:12;;49066:108;;;1549:25:1;;;1537:2;1522:18;49066:108:0;1403:177:1;99880:186:0;;;;;;:::i;:::-;;:::i;94757:109::-;;;:::i;:::-;;;;;;;:::i;81809:1298::-;;;;;;:::i;:::-;;:::i;51078:261::-;;;;;;:::i;:::-;;:::i;39866:131::-;;;;;;:::i;:::-;39940:7;39967:12;;;:6;:12;;;;;:22;;;;39866:131;97689:282;;;;;;:::i;:::-;;:::i;88857:250::-;;;:::i;98366:268::-;;;;;;:::i;:::-;;:::i;40307:147::-;;;;;;:::i;:::-;;:::i;65324:356::-;;;;;;:::i;:::-;;:::i;48908:93::-;;;48991:2;4240:36:1;;4228:2;4213:18;48908:93:0;4098:184:1;100156:192:0;;;;;;:::i;:::-;;:::i;86946:1022::-;;;;;;:::i;:::-;;:::i;61865:29::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;4451:32:1;;;4433:51;;4421:2;4406:18;61865:29:0;4287:203:1;41451:218:0;;;;;;:::i;:::-;;:::i;51748:238::-;;;;;;:::i;:::-;;:::i;67174:468::-;;;;;;:::i;:::-;;:::i;100535:67::-;;;:::i;72829:1863::-;;;;;;:::i;:::-;;:::i;92320:327::-;;;;;;:::i;:::-;;:::i;61978:33::-;;;;;;60077:29;;;;;-1:-1:-1;;;;;60077:29:0;;;102852:361;;;;;;:::i;:::-;;:::i;80529:1080::-;;;;;;:::i;:::-;;:::i;97338:288::-;;;;;;:::i;:::-;;:::i;96713:558::-;;;;;;:::i;:::-;;:::i;60823:52::-;;60873:2;60823:52;;31048:86;31119:7;;;;31048:86;;61750:65;;;;;;:::i;:::-;;:::i;:::-;;;;5245:25:1;;;5301:2;5286:18;;5279:34;;;;5329:18;;;5322:34;;;;5387:2;5372:18;;5365:34;;;;5443:14;5436:22;5430:3;5415:19;;5408:51;5503:14;5496:22;5490:3;5475:19;;5468:51;-1:-1:-1;;;;;5556:32:1;5550:3;5535:19;;5528:61;5633:14;5626:22;5620:3;5605:19;;5598:51;5232:3;5217:19;61750:65:0;4920:735:1;99571:228:0;;;;;;:::i;:::-;;:::i;59971:23::-;;;;;-1:-1:-1;;;;;59971:23:0;;;95136:890;;;;;;:::i;:::-;;:::i;60254:51::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;101200:121;;;;;;:::i;:::-;-1:-1:-1;;;;;101287:26:0;101263:4;101287:26;;;:17;:26;;;;;;;;;101200:121;74979:2499;;;;;;:::i;:::-;;:::i;59725:38::-;;;;;;66831:173;;;;;;:::i;:::-;;:::i;25038:103::-;;;:::i;101416:125::-;;;;;;:::i;:::-;-1:-1:-1;;;;;101505:28:0;101481:4;101505:28;;;:19;:28;;;;;;;;;101416:125;60001:30;;;;;-1:-1:-1;;;;;60001:30:0;;;60746:54;;60798:2;60746:54;;45492:216;;;:::i;59782:35::-;;;;;;66230:230;;;;;;:::i;:::-;;:::i;100674:98::-;;;:::i;96088:503::-;;;:::i;:::-;;;;7058:25:1;;;7114:2;7099:18;;7092:34;;;;7142:18;;;7135:34;;;;7200:2;7185:18;;7178:34;7256:14;7249:22;7243:3;7228:19;;7221:51;7045:3;7030:19;96088:503:0;6805:473:1;59848:33:0;;;;;;100409:63;;;:::i;59376:66::-;;59417:25;59376:66;;60344:47;;;;;;83402:1406;;;;;;:::i;:::-;;:::i;24397:87::-;24470:6;;-1:-1:-1;;;;;24470:6:0;24397:87;;59482:42;;59521:3;59482:42;;59282:65;;59321:26;59282:65;;38339:147;;;;;;:::i;:::-;;:::i;61901:45::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;92772:962;;;;;;:::i;:::-;;:::i;84949:507::-;;;;;;:::i;:::-;;:::i;48156:104::-;;;:::i;93895:802::-;;;;;;:::i;:::-;;:::i;:::-;;;;7558:25:1;;;7614:2;7599:18;;7592:34;;;;7642:18;;;7635:34;;;;7700:2;7685:18;;7678:34;7756:14;7749:22;7743:3;7728:19;;7721:51;7816:14;7809:22;7803:3;7788:19;;7781:51;7545:3;7530:19;93895:802:0;7283:555:1;37444:49:0;;37489:4;37444:49;;52489:436;;;;;;:::i;:::-;;:::i;59550:46::-;;59592:4;59550:46;;65781:338;;;;;;:::i;:::-;;:::i;62018:32::-;;;;;;49570:193;;;;;;:::i;:::-;;:::i;89308:2175::-;;;;;;:::i;:::-;;:::i;98965:233::-;;;;;;:::i;:::-;;:::i;67894:685::-;;;;;;:::i;:::-;;:::i;94927:108::-;95008:12;:19;94927:108;;85664:1085;;;;;;:::i;:::-;;:::i;66534:128::-;;;;;;:::i;:::-;;:::i;60590:49::-;;60631:8;60590:49;;59664:35;;;;;;60456:66;;-1:-1:-1;;;;;;;;;;;60456:66:0;;59904:27;;;;;;60038:32;;;;;-1:-1:-1;;;;;60038:32:0;;;60198:49;;;;;;:::i;:::-;;;;;;;;;;;;;;;;60664:57;;60719:2;60664:57;;100837:286;101037:15;;101054:18;;101074:15;;101091:13;;101106:8;;100837:286;;;8102:25:1;;;8158:2;8143:18;;8136:34;;;;8186:18;;;8179:34;;;;8244:2;8229:18;;8222:34;8287:3;8272:19;;8265:35;8089:3;8074:19;100837:286:0;7843:463:1;40747:149:0;;;;;;:::i;:::-;;:::i;91613:590::-;;;;;;:::i;:::-;;:::i;49826:151::-;;;;;;:::i;:::-;;:::i;98032:278::-;;;;;;:::i;:::-;;:::i;44580:101::-;44660:13;;-1:-1:-1;;;;;44660:13:0;44580:101;;101966:782;;;;;;:::i;:::-;;:::i;:::-;;;;8801:25:1;;;8857:2;8842:18;;8835:34;;;;8912:14;;8905:22;8885:18;;;8878:50;;;;8959:2;8944:18;;8937:34;8788:3;8773:19;101966:782:0;8576:401:1;99263:239:0;;;;;;:::i;:::-;;:::i;44880:181::-;;;;;;:::i;:::-;;:::i;98690:212::-;;;;;;:::i;:::-;;:::i;61586:59::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;61586:59:0;;;;;-1:-1:-1;;;61586:59:0;;;;;38043:204;38128:4;-1:-1:-1;;;;;;38152:47:0;;-1:-1:-1;;;38152:47:0;;:87;;-1:-1:-1;;;;;;;;;;17237:40:0;;;38203:36;38145:94;38043:204;-1:-1:-1;;38043:204:0:o;47937:100::-;47991:13;48024:5;48017:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47937:100;:::o;50297:201::-;50380:4;751:10;50436:32;751:10;50452:7;50461:6;50436:8;:32::i;:::-;-1:-1:-1;50486:4:0;;50297:201;-1:-1:-1;;;50297:201:0:o;88063:530::-;24283:13;:11;:13::i;:::-;34332:21:::1;:19;:21::i;:::-;-1:-1:-1::0;;;;;88180:26:0;::::2;;::::0;;;:20:::2;:26;::::0;;;;:33;88172:41;::::2;88164:76;;;;-1:-1:-1::0;;;88164:76:0::2;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1::0;;;;;88286:26:0;::::2;88251:32;88286:26:::0;;;:20:::2;:26;::::0;;;;:33;;88313:5;;88286:33;::::2;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;::::2;::::0;;::::2;;88338:17;::::0;::::2;::::0;88286:33;;-1:-1:-1;88338:17:0::2;;88330:56;;;;-1:-1:-1::0;;;88330:56:0::2;;;;;;;:::i;:::-;88419:18;::::0;::::2;::::0;;::::2;;::::0;;::::2;::::0;::::2;88418:19;88397:40:::0;::::2;-1:-1:-1::0;;88397:40:0;;::::2;::::0;;;::::2;::::0;;;;88522:63:::2;::::0;;88549:18;;;::::2;;10398:14:1::0;10391:22;10373:41;;88569:15:0::2;10445:2:1::0;10430:18;;10423:34;-1:-1:-1;;;;;88522:63:0;::::2;::::0;::::2;::::0;10346:18:1;88522:63:0::2;;;;;;;;88153:440;34376:20:::1;33770:1:::0;34896:7;:22;34713:213;34376:20:::1;88063:530:::0;;:::o;99880:186::-;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;99967:26:0;::::1;;::::0;;;:17:::1;:26;::::0;;;;;;;;:37;;-1:-1:-1;;99967:37:0::1;::::0;::::1;;::::0;;::::1;::::0;;;100020:38;;10636:51:1;;;10703:18;;;10696:50;100020:38:0::1;::::0;10609:18:1;100020:38:0::1;;;;;;;;99880:186:::0;;:::o;94757:109::-;94810:16;94846:12;94839:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;94839:19:0;;;;;;;;;;;;;;;;;;;;;;94757:109;:::o;81809:1298::-;24283:13;:11;:13::i;:::-;34332:21:::1;:19;:21::i;:::-;81895:8:::2;81909:26;81930:4;81909:20;:26::i;:::-;81894:41;;;81954:3;81946:42;;;;-1:-1:-1::0;;;81946:42:0::2;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;82039:26:0;::::2;82001:35;82039:26:::0;;;:20:::2;:26;::::0;;;;;82001:35;82116:723:::2;82140:16:::0;;82136:20;::::2;82116:723;;;82178:32;82213:9;82223:1;82213:12;;;;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;::::2;::::0;;::::2;;82245:17;::::0;::::2;::::0;82213:12;;-1:-1:-1;82245:17:0::2;;82240:67;;82283:8;;;82240:67;82321:19;82343:42;82359:8;82369:15;82343;:42::i;:::-;82321:64;;82400:19;82436:8;:23;;;82422:11;:37;:77;;82476:8;:23;;;82422:77;;;82462:11;82422:77;82400:99;;82514:20;82560:11;82537:8;:20;;;:34;:77;;82613:1;82537:77;;;82575:20:::0;;:34:::2;::::0;82598:11;;82575:34:::2;:::i;:::-;82514:100:::0;-1:-1:-1;82633:16:0;;82629:199:::2;;82696:20:::0;;82670:23:::2;::::0;::::2;:46:::0;82735:33:::2;82756:12:::0;82735:33;::::2;:::i;:::-;82787:17;::::0;::::2;:25:::0;;-1:-1:-1;;82787:25:0::2;::::0;;82735:33;-1:-1:-1;82629:199:0::2;82163:676;;;;82116:723;82158:3;;82116:723;;;;82877:1;82857:17;:21;82849:58;;;::::0;-1:-1:-1;;;82849:58:0;;11354:2:1;82849:58:0::2;::::0;::::2;11336:21:1::0;11393:2;11373:18;;;11366:30;11432:26;11412:18;;;11405:54;11476:18;;82849:58:0::2;11152:348:1::0;82849:58:0::2;82935:17;82918:13;;:34;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;83039:60:0::2;::::0;;11679:25:1;;;83083:15:0::2;11735:2:1::0;11720:18;;11713:34;-1:-1:-1;;;;;83039:60:0;::::2;::::0;::::2;::::0;11652:18:1;83039:60:0::2;;;;;;;81883:1224;;;34376:20:::1;33770:1:::0;34896:7;:22;34713:213;34376:20:::1;81809:1298:::0;:::o;51078:261::-;51175:4;751:10;51233:38;51249:4;751:10;51264:6;51233:15;:38::i;:::-;51282:27;51292:4;51298:2;51302:6;51282:9;:27::i;:::-;-1:-1:-1;51327:4:0;;51078:261;-1:-1:-1;;;;51078:261:0:o;97689:282::-;24283:13;:11;:13::i;:::-;97834:15:::1;;97822:8;;97806:13;;97796:7;97775:18;;:28;;;;:::i;:::-;:44;;;;:::i;:::-;:55;;;;:::i;:::-;:74;;97767:113;;;;-1:-1:-1::0;;;97767:113:0::1;;;;;;;:::i;:::-;97891:15;:25:::0;;;97932:31:::1;::::0;1549:25:1;;;97932:31:0::1;::::0;1537:2:1;1522:18;97932:31:0::1;;;;;;;;97689:282:::0;:::o;88857:250::-;24283:13;:11;:13::i;:::-;88949:12:::1;:19:::0;88920:26:::1;88979:121;89003:18;88999:1;:22;88979:121;;;89043:45;89072:12;89085:1;89072:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;89072:15:0::1;89043:28;:45::i;:::-;89023:3;;88979:121;;98366:268:::0;24283:13;:11;:13::i;:::-;98511:15:::1;;98500:7;98484:13;;98466:15;;98445:18;;:36;;;;:::i;:::-;:52;;;;:::i;:::-;:62;;;;:::i;:::-;:81;;98437:120;;;;-1:-1:-1::0;;;98437:120:0::1;;;;;;;:::i;:::-;98568:8;:18:::0;;;98602:24:::1;::::0;1549:25:1;;;98602:24:0::1;::::0;1537:2:1;1522:18;98602:24:0::1;1403:177:1::0;40307:147:0;39940:7;39967:12;;;:6;:12;;;;;:22;;;37935:16;37946:4;37935:10;:16::i;:::-;40421:25:::1;40432:4;40438:7;40421:10;:25::i;:::-;40307:147:::0;;;:::o;65324:356::-;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;65406:21:0;::::1;65398:49;;;;-1:-1:-1::0;;;65398:49:0::1;;;;;;;:::i;:::-;65458:34;-1:-1:-1::0;;;;;;;;;;;65484:7:0::1;65458:10;:34::i;:::-;-1:-1:-1::0;;;;;65589:26:0;::::1;;::::0;;;:17:::1;:26;::::0;;;;;:33;;-1:-1:-1;;65589:33:0::1;65618:4;65589:33;::::0;;65638:34;65661:10:::1;::::0;65589:26;65638:34:::1;::::0;::::1;65324:356:::0;:::o;100156:192::-;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;100245:28:0;::::1;;::::0;;;:19:::1;:28;::::0;;;;;;;;:39;;-1:-1:-1;;100245:39:0::1;::::0;::::1;;::::0;;::::1;::::0;;;100300:40;;10636:51:1;;;10703:18;;;10696:50;100300:40:0::1;::::0;10609:18:1;100300:40:0::1;10468:284:1::0;86946:1022:0;24283:13;:11;:13::i;:::-;34332:21:::1;:19;:21::i;:::-;-1:-1:-1::0;;;;;87065:26:0;::::2;;::::0;;;:20:::2;:26;::::0;;;;:33;87057:41;::::2;87049:76;;;;-1:-1:-1::0;;;87049:76:0::2;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;87171:26:0;::::2;87136:32;87171:26:::0;;;:20:::2;:26;::::0;;;;:33;;87198:5;;87171:33;::::2;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;::::2;::::0;;::::2;;87223:17;::::0;::::2;::::0;87171:33;;-1:-1:-1;87223:17:0::2;;87215:56;;;;-1:-1:-1::0;;;87215:56:0::2;;;;;;;:::i;:::-;87306:15;87284:19;87360:38;87376:8:::0;87306:15;87360::::2;:38::i;:::-;87332:66;;87409:19;87451:8;:23;;;87431:17;:43;:89;;87497:8;:23;;;87431:89;;;87477:17;87431:89;87409:111;;87531:20;87577:11;87554:8;:20;;;:34;:77;;87630:1;87554:77;;;87592:20:::0;;:34:::2;::::0;87615:11;;87592:34:::2;:::i;:::-;87644:17;::::0;::::2;:25:::0;;-1:-1:-1;;;;;;87680:27:0;-1:-1:-1;;;87680:27:0::2;::::0;;87664:5:::2;87718:18;::::0;::::2;:22:::0;;;87751:16:::2;::::0;::::2;:20:::0;;;87784:14:::2;:30:::0;;87531:100;;-1:-1:-1;87531:100:0;;87784:14;;87664:5;87784:30:::2;::::0;87531:100;;87784:30:::2;:::i;:::-;::::0;;;-1:-1:-1;;87899:61:0::2;::::0;;11679:25:1;;;87944:15:0::2;11735:2:1::0;11720:18;;11713:34;-1:-1:-1;;;;;87899:61:0;::::2;::::0;::::2;::::0;11652:18:1;87899:61:0::2;;;;;;;87038:930;;;;;34376:20:::1;33770:1:::0;34896:7;:22;34713:213;61865:29;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;61865:29:0;;-1:-1:-1;61865:29:0;:::o;41451:218::-;-1:-1:-1;;;;;41547:23:0;;751:10;41547:23;41539:83;;;;-1:-1:-1;;;41539:83:0;;12659:2:1;41539:83:0;;;12641:21:1;12698:2;12678:18;;;12671:30;12737:34;12717:18;;;12710:62;-1:-1:-1;;;12788:18:1;;;12781:45;12843:19;;41539:83:0;12457:411:1;41539:83:0;41635:26;41647:4;41653:7;41635:11;:26::i;51748:238::-;51836:4;751:10;51892:64;751:10;51908:7;51945:10;51917:25;751:10;51908:7;51917:9;:25::i;:::-;:38;;;;:::i;:::-;51892:8;:64::i;67174:468::-;-1:-1:-1;;;;;67269:22:0;;67244:7;67269:22;;;:13;:22;;;;;;;;67264:64;;-1:-1:-1;67315:1:0;;67174:468;-1:-1:-1;67174:468:0:o;67264:64::-;-1:-1:-1;;;;;67376:29:0;;67338:35;67376:29;;;:20;:29;;;;;;67338:35;67444:168;67468:16;;67464:20;;67444:168;;;67510:9;67520:1;67510:12;;;;;;;;:::i;:::-;;;;;;;;;:21;:12;;;;;:21;;;;67506:95;;;67561:9;67571:1;67561:12;;;;;;;;:::i;:::-;;;;;;;;;;;:24;;;67552:33;;;;;:::i;:::-;;;67506:95;67486:3;;67444:168;;;-1:-1:-1;67629:5:0;67174:468;-1:-1:-1;;;67174:468:0:o;100535:67::-;24283:13;:11;:13::i;:::-;100584:10:::1;:8;:10::i;:::-;100535:67::o:0;72829:1863::-;-1:-1:-1;;;;;;;;;;;37935:16:0;37946:4;37935:10;:16::i;:::-;34332:21:::1;:19;:21::i;:::-;-1:-1:-1::0;;;;;72955:18:0;::::2;72947:51;;;::::0;-1:-1:-1;;;72947:51:0;;13075:2:1;72947:51:0::2;::::0;::::2;13057:21:1::0;13114:2;13094:18;;;13087:30;-1:-1:-1;;;13133:18:1;;;13126:50;13193:18;;72947:51:0::2;12873:344:1::0;72947:51:0::2;73026:1;73017:6;:10;73009:55;;;;-1:-1:-1::0;;;73009:55:0::2;;;;;;;:::i;:::-;73110:6;73085:21;73095:10;73085:9;:21::i;:::-;:31;;73077:75;;;::::0;-1:-1:-1;;;73077:75:0;;13785:2:1;73077:75:0::2;::::0;::::2;13767:21:1::0;13824:2;13804:18;;;13797:30;13863:33;13843:18;;;13836:61;13914:18;;73077:75:0::2;13583:355:1::0;73077:75:0::2;73212:35;73222:10;73234:4;73240:6;73212:9;:35::i;:::-;73358:15;73395:1;73377:15;;:19;:53;;;;-1:-1:-1::0;73419:10:0::2;73401:29;::::0;;;:17:::2;:29;::::0;;;;;::::2;;73400:30;73377:53;:81;;;;-1:-1:-1::0;;;;;;73435:23:0;::::2;;::::0;;;:17:::2;:23;::::0;;;;;::::2;;73434:24;73377:81;73358:101;;73470:22;73495:10;:79;;73568:6;73495:79;;;59592:4;73529:15;;73520:6;:24;;;;:::i;:::-;73519:44;;;;:::i;:::-;73509:55;::::0;:6;:55:::2;:::i;:::-;73653:66;::::0;;11679:25:1;;;73703:15:0::2;11735:2:1::0;11720:18;;11713:34;73470:104:0;;-1:-1:-1;;;;;;73653:66:0;::::2;::::0;::::2;::::0;11652:18:1;73653:66:0::2;;;;;;;73752:15;73732:17;73796:26;73752:15:::0;73809:12:::2;73796:26;:::i;:::-;73778:44;;73869:34;73906:294;;;;;;;;73950:14;73906:294;;;;73995:1;73906:294;;;;74022:9;73906:294;;;;74055:7;73906:294;;;;74087:4;73906:294;;;;;;74117:4;73906:294;;;;;;74145:10;-1:-1:-1::0;;;;;73906:294:0::2;;;;;74183:5;73906:294;;;;::::0;73869:331:::2;;74304:11;74279:16;:22;74296:4;-1:-1:-1::0;;;;;74279:22:0::2;-1:-1:-1::0;;;;;74279:22:0::2;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;74279:36:0::2;;;;;-1:-1:-1::0;;;;;74279:36:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74384:20;:26;74405:4;-1:-1:-1::0;;;;;74384:26:0::2;-1:-1:-1::0;;;;;74384:26:0::2;;;;;;;;;;;;74416:11;74384:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;74384:44:0::2;;;;;-1:-1:-1::0;;;;;74384:44:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74446:13;:19;74460:4;-1:-1:-1::0;;;;;74446:19:0::2;-1:-1:-1::0;;;;;74446:19:0::2;;;;;;;;;;;;;;;;;;;;;;74441:117;;74482:12;:23:::0;;::::2;::::0;;::::2;::::0;;;;::::2;::::0;;-1:-1:-1;;;;;;74482:23:0::2;-1:-1:-1::0;;;;;74482:23:0;::::2;::::0;;::::2;::::0;;;-1:-1:-1;74520:19:0;;;:13:::2;74482:23;74520:19:::0;;;;:26;;-1:-1:-1;;74520:26:0::2;::::0;;::::2;::::0;;74441:117:::2;74588:14;74570;;:32;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;74620:64:0::2;::::0;;14540:25:1;;;14596:2;14581:18;;14574:34;;;14624:18;;;14617:34;;;-1:-1:-1;;;;;74620:64:0;::::2;::::0;::::2;::::0;14528:2:1;14513:18;74620:64:0::2;;;;;;;;72936:1756;;;;;34376:20:::1;33770:1:::0;34896:7;:22;34713:213;92320:327;-1:-1:-1;;;;;92442:26:0;;92384:7;92442:26;;;:20;:26;;;;;92384:7;;92507:110;92531:16;;92527:20;;92507:110;;;92578:9;92588:1;92578:12;;;;;;;;:::i;:::-;;;;;;;;;;;:27;;;92569:36;;;;;:::i;:::-;;-1:-1:-1;92549:3:0;;92507:110;;102852:361;24283:13;:11;:13::i;:::-;34332:21:::1;:19;:21::i;:::-;-1:-1:-1::0;;;;;102963:16:0;::::2;102955:44;;;;-1:-1:-1::0;;;102955:44:0::2;;;;;;;:::i;:::-;103027:1;103018:6;:10;103010:55;;;;-1:-1:-1::0;;;103010:55:0::2;;;;;;;:::i;:::-;103112:6;103084:24;103102:4;103084:9;:24::i;:::-;:34;;103076:76;;;::::0;-1:-1:-1;;;103076:76:0;;14864:2:1;103076:76:0::2;::::0;::::2;14846:21:1::0;14903:2;14883:18;;;14876:30;14942:31;14922:18;;;14915:59;14991:18;;103076:76:0::2;14662:353:1::0;103076:76:0::2;103163:42;103187:4;103194:2;103198:6;103163:15;:42::i;:::-;34376:20:::1;33770:1:::0;34896:7;:22;34713:213;80529:1080;24283:13;:11;:13::i;:::-;34332:21:::1;:19;:21::i;:::-;-1:-1:-1::0;;;;;80655:26:0;::::2;;::::0;;;:20:::2;:26;::::0;;;;:33;80647:41;::::2;80639:76;;;;-1:-1:-1::0;;;80639:76:0::2;;;;;;;:::i;:::-;80743:1;80734:6;:10;80726:55;;;;-1:-1:-1::0;;;80726:55:0::2;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;80827:26:0;::::2;80792:32;80827:26:::0;;;:20:::2;:26;::::0;;;;:33;;80854:5;;80827:33;::::2;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;::::2;::::0;;::::2;;80879:17;::::0;::::2;::::0;80827:33;;-1:-1:-1;80879:17:0::2;;80871:56;;;;-1:-1:-1::0;;;80871:56:0::2;;;;;;;:::i;:::-;80962:15;80940:19;81016:38;81032:8:::0;80962:15;81016::::2;:38::i;:::-;80988:66;;81065:19;81107:8;:23;;;81087:17;:43;:89;;81153:8;:23;;;81087:89;;;81133:17;81087:89;81065:111;;81187:31;81244:11;81221:8;:20;;;:34;:77;;81297:1;81221:77;;;81259:20:::0;;:34:::2;::::0;81282:11;;81259:34:::2;:::i;:::-;81187:111;;81327:23;81317:6;:33;;81309:84;;;::::0;-1:-1:-1;;;81309:84:0;;15222:2:1;81309:84:0::2;::::0;::::2;15204:21:1::0;15261:2;15241:18;;;15234:30;15300:34;15280:18;;;15273:62;-1:-1:-1;;;15351:18:1;;;15344:36;15397:19;;81309:84:0::2;15020:402:1::0;81309:84:0::2;81433:6;81406:8;:23;;;:33;;;;;;;:::i;:::-;;;;;;;;81467:6;81450:13;;:23;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;81558:43:0::2;::::0;;11679:25:1;;;81585:15:0::2;11735:2:1::0;11720:18;;11713:34;-1:-1:-1;;;;;81558:43:0;::::2;::::0;::::2;::::0;11652:18:1;81558:43:0::2;11505:248:1::0;97338:288:0;24283:13;:11;:13::i;:::-;97483:15:::1;::::0;97471:8:::1;::::0;97455:13:::1;::::0;97437:15:::1;::::0;97427:25:::1;::::0;:7;:25:::1;:::i;:::-;:41;;;;:::i;:::-;:52;;;;:::i;:::-;:71;;97419:110;;;;-1:-1:-1::0;;;97419:110:0::1;;;;;;;:::i;:::-;97540:18;:28:::0;;;97584:34:::1;::::0;1549:25:1;;;97584:34:0::1;::::0;1537:2:1;1522:18;97584:34:0::1;1403:177:1::0;96713:558:0;24283:13;:11;:13::i;:::-;59521:3:::1;96802:10;:26;;96794:56;;;::::0;-1:-1:-1;;;96794:56:0;;15629:2:1;96794:56:0::1;::::0;::::1;15611:21:1::0;15668:2;15648:18;;;15641:30;-1:-1:-1;;;15687:18:1;;;15680:47;15744:18;;96794:56:0::1;15427:341:1::0;96794:56:0::1;96971:14:::0;;96967:212:::1;;97095:10;97083:8;;97067:13;;97049:15;;97028:18;;:36;;;;:::i;:::-;:52;;;;:::i;:::-;:63;;;;:::i;:::-;:77;;97002:165;;;;-1:-1:-1::0;;;97002:165:0::1;;;;;;;:::i;:::-;97189:15;:28:::0;;;97233:30:::1;::::0;1549:25:1;;;97233:30:0::1;::::0;1537:2:1;1522:18;97233:30:0::1;1403:177:1::0;61750:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;61750:65:0;;-1:-1:-1;61750:65:0;;;;;;;;;;;;;-1:-1:-1;;;;;61750:65:0;;;;;-1:-1:-1;;;61750:65:0;;;;:::o;99571:228::-;24283:13;:11;:13::i;:::-;99667:1:::1;99655:9;:13;99647:65;;;::::0;-1:-1:-1;;;99647:65:0;;15975:2:1;99647:65:0::1;::::0;::::1;15957:21:1::0;16014:2;15994:18;;;15987:30;16053:34;16033:18;;;16026:62;-1:-1:-1;;;16104:18:1;;;16097:37;16151:19;;99647:65:0::1;15773:403:1::0;99647:65:0::1;99723:11;:23:::0;;;99762:29:::1;::::0;1549:25:1;;;99762:29:0::1;::::0;1537:2:1;1522:18;99762:29:0::1;1403:177:1::0;95136:890:0;-1:-1:-1;;;;;95255:26:0;;95200:4;95255:26;;;:20;:26;;;;;95298:16;;:21;;95294:66;;-1:-1:-1;95343:5:0;;95136:890;-1:-1:-1;;95136:890:0:o;95294:66::-;95377:9;95372:623;95396:16;;95392:20;;95372:623;;;95434:32;95469:9;95479:1;95469:12;;;;;;;;:::i;:::-;;;;;;;;;;;;;;95501:17;;;;95469:12;;-1:-1:-1;95501:17:0;;95496:67;;95539:8;;;95496:67;95648:16;;;;95599:15;;95633:31;;95629:80;;95685:8;;;;95629:80;95741:8;:18;;;95727:11;:32;95723:85;;;-1:-1:-1;95787:5:0;;95136:890;-1:-1:-1;;;;;95136:890:0:o;95723:85::-;95822:19;95844:38;95860:8;95870:11;95844:15;:38::i;:::-;95915:20;;95822:60;;-1:-1:-1;95901:34:0;;95897:87;;;-1:-1:-1;95963:5:0;;95136:890;-1:-1:-1;;;;;;95136:890:0:o;95897:87::-;95419:576;;;95372:623;95414:3;;95372:623;;74979:2499;-1:-1:-1;;;;;;;;;;;37935:16:0;37946:4;37935:10;:16::i;:::-;34332:21:::1;:19;:21::i;:::-;75155:30:::0;;::::2;75147:65;;;::::0;-1:-1:-1;;;75147:65:0;;16383:2:1;75147:65:0::2;::::0;::::2;16365:21:1::0;16422:2;16402:18;;;16395:30;-1:-1:-1;;;16441:18:1;;;16434:52;16503:18;;75147:65:0::2;16181:346:1::0;75147:65:0::2;75231:16:::0;75223:41:::2;;;::::0;-1:-1:-1;;;75223:41:0;;16734:2:1;75223:41:0::2;::::0;::::2;16716:21:1::0;16773:2;16753:18;;;16746:30;-1:-1:-1;;;16792:18:1;;;16785:42;16844:18;;75223:41:0::2;16532:336:1::0;75223:41:0::2;75277:25;::::0;75317:183:::2;75337:18:::0;;::::2;75317:183;;;75401:1;75381:5:::0;;75387:1;75381:8;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;75381:22:0::2;;;:40;;;;;75420:1;75407:7;;75415:1;75407:10;;;;;;;:::i;:::-;;;;;;;:14;75381:40;75377:112;;;75463:7;;75471:1;75463:10;;;;;;;:::i;:::-;;;;;;;75442:31;;;;;:::i;:::-;;;75377:112;75357:3;;75317:183;;;;75543:17;75518:21;75528:10;75518:9;:21::i;:::-;:42;;75510:91;;;::::0;-1:-1:-1;;;75510:91:0;;17075:2:1;75510:91:0::2;::::0;::::2;17057:21:1::0;17114:2;17094:18;;;17087:30;17153:34;17133:18;;;17126:62;-1:-1:-1;;;17204:18:1;;;17197:34;17248:19;;75510:91:0::2;16873:400:1::0;75510:91:0::2;75634:15;75614:17;75678:26;75634:15:::0;75691:12:::2;75678:26;:::i;:::-;75660:44:::0;-1:-1:-1;75756:9:0::2;75751:1720;75771:16:::0;;::::2;75751:1720;;;75833:1;75813:5:::0;;75819:1;75813:8;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;75813:22:0::2;;;:40;;;;;75852:1;75839:7;;75847:1;75839:10;;;;;;;:::i;:::-;;;;;;;:14;75813:40;75809:1651;;;75874:43;75884:10;75896:5;;75902:1;75896:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;75906:7;;75914:1;75906:10;;;;;;;:::i;:::-;;;;;;;75874:9;:43::i;:::-;76014:15;76051:1;76033:15;;:19;:74;;;;-1:-1:-1::0;76096:10:0::2;76078:29;::::0;;;:17:::2;:29;::::0;;;;;::::2;;76077:30;76033:74;:127;;;;;76133:17;:27;76151:5;;76157:1;76151:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76133:27:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;76133:27:0;;::::2;;76132:28;76033:127;76014:147;;76180:22;76205:10;:133;;76328:7;;76336:1;76328:10;;;;;;;:::i;:::-;;;;;;;76205:133;;;59592:4;76268:15;;76255:7;;76263:1;76255:10;;;;;;;:::i;:::-;;;;;;;:28;;;;:::i;:::-;76254:48;;;;:::i;:::-;76240:7;;76248:1;76240:10;;;;;;;:::i;:::-;;;;;;;:63;;;;:::i;:::-;76180:158;;76390:5;;76396:1;76390:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76362:70:0::2;;76400:14;76416:15;76362:70;;;;;;11679:25:1::0;;;11735:2;11720:18;;11713:34;11667:2;11652:18;;11505:248;76362:70:0::2;;;;;;;;76490:366;::::0;;::::2;::::0;::::2;::::0;;;;;76453:34:::2;76490:366;::::0;::::2;::::0;;;;;;;;;;;;;;;76711:4:::2;76490:366:::0;;;;;;;;;;76785:10:::2;76490:366:::0;;;;;;;;;;;;;76951:16:::2;::::0;76968:5;;76974:1;76968:8;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76951:26:0;;::::2;::::0;;::::2;::::0;;::::2;::::0;;;;;;;;-1:-1:-1;76951:26:0;;;:40;;;;;;::::2;::::0;::::2;::::0;::::2;::::0;;;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;;::::2;::::0;-1:-1:-1;;76951:40:0;;;;::::2;;-1:-1:-1::0;;76951:40:0;;;;;::::2;::::0;::::2;;::::0;;;::::2;::::0;;;::::2;-1:-1:-1::0;;;;;;76951:40:0;;;;;::::2;::::0;;;::::2;-1:-1:-1::0;;;;76951:40:0;;-1:-1:-1;;;76951:40:0;::::2;;::::0;;;::::2;::::0;;;::::2;::::0;;;77076:20:::2;::::0;77097:5;;77103:1;77097:8;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;77076:30:0;;::::2;::::0;;::::2;::::0;;::::2;::::0;;;;;;;;-1:-1:-1;77076:30:0;;;:48;;::::2;::::0;;::::2;::::0;;;;;;;;;;::::2;::::0;;::::2;;::::0;;;;;::::2;::::0;;;::::2;::::0;;;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;;-1:-1:-1::0;;;77076:48:0::2;-1:-1:-1::0;;;;77076:48:0;;;::::2;::::0;::::2;::::0;-1:-1:-1;;;;;;77076:48:0;::::2;;;;-1:-1:-1::0;;77076:48:0;::::2;;::::0;;;;-1:-1:-1;;77076:48:0;;;;;;;;;;::::2;::::0;;;;;;;;::::2;::::0;;;77150:13:::2;::::0;77164:5;;77170:1;77164:8;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;77150:23:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;77150:23:0;;::::2;;77145:153;;77198:12;77216:5;;77222:1;77216:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;77198:27:::0;;::::2;::::0;;::::2;::::0;;-1:-1:-1;77198:27:0;;;::::2;::::0;;;;::::2;::::0;;-1:-1:-1;;;;;;77198:27:0::2;-1:-1:-1::0;;;;;77198:27:0;;;::::2;::::0;;;::::2;::::0;;;;77248:13:::2;::::0;77262:5;;77268:1;77262:8;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;77248:23:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;77248:23:0;:30;;-1:-1:-1;;77248:30:0::2;::::0;::::2;;::::0;;;::::2;::::0;;77145:153:::2;77336:14;77318;;:32;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;77399:5:0;;-1:-1:-1;77399:5:0;77405:1;77399:8;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;77376:68;::::0;;14540:25:1;;;14596:2;14581:18;;14574:34;;;14624:18;;;14617:34;;;-1:-1:-1;;;;;77376:68:0;;;::::2;::::0;::::2;::::0;14528:2:1;14513:18;77376:68:0::2;;;;;;;75855:1605;;;75809:1651;75789:3;;75751:1720;;;;75136:2342;;;34376:20:::1;33770:1:::0;34896:7;:22;34713:213;34376:20:::1;74979:2499:::0;;;;;:::o;66831:173::-;-1:-1:-1;;;;;49338:18:0;;66897:7;49338:18;;;;;;;;;;;66972:24;49237:127;25038:103;24283:13;:11;:13::i;:::-;25103:30:::1;25130:1;25103:18;:30::i;45492:216::-:0;44660:13;;751:10;;-1:-1:-1;;;;;44660:13:0;45593:24;;45585:78;;;;-1:-1:-1;;;45585:78:0;;17480:2:1;45585:78:0;;;17462:21:1;17519:2;17499:18;;;17492:30;17558:34;17538:18;;;17531:62;-1:-1:-1;;;17609:18:1;;;17602:39;17658:19;;45585:78:0;17278:405:1;45585:78:0;45674:26;45693:6;45674:18;:26::i;66230:230::-;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;66317:23:0;::::1;66309:58;;;;-1:-1:-1::0;;;66309:58:0::1;;;;;;;:::i;:::-;66378:14;:26:::0;;-1:-1:-1;;;;;;66378:26:0::1;-1:-1:-1::0;;;;;66378:26:0;::::1;::::0;;::::1;::::0;;;66420:32:::1;::::0;4433:51:1;;;66420:32:0::1;::::0;4421:2:1;4406:18;66420:32:0::1;4287:203:1::0;100674:98:0;24283:13;:11;:13::i;:::-;30653:19:::1;:17;:19::i;:::-;100745::::2;:17;:19::i;96088:503::-:0;96179:25;96219:28;96262:27;96304:23;96342:21;96413:12;:19;;;;96447:14;;96476:13;;96521;;96504:14;;:30;;;;:::i;:::-;96549:12;:19;96391:192;;;;-1:-1:-1;96391:192:0;;-1:-1:-1;96391:192:0;-1:-1:-1;96549:23:0;;;;-1:-1:-1;96088:503:0;-1:-1:-1;96088:503:0:o;100409:63::-;24283:13;:11;:13::i;:::-;100456:8:::1;:6;:8::i;83402:1406::-:0;34332:21;:19;:21::i;:::-;-1:-1:-1;;;;;83530:26:0;::::1;;::::0;;;:20:::1;:26;::::0;;;;:33;83522:41;::::1;83514:76;;;;-1:-1:-1::0;;;83514:76:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;83636:26:0;::::1;83601:32;83636:26:::0;;;:20:::1;:26;::::0;;;;:33;;83663:5;;83636:33;::::1;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;;83688:17;::::0;::::1;::::0;83636:33;;-1:-1:-1;83688:17:0::1;;83680:56;;;;-1:-1:-1::0;;;83680:56:0::1;;;;;;;:::i;:::-;83769:16;::::0;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;83769:16:0::1;83755:10;:30;83747:64;;;::::0;-1:-1:-1;;;83747:64:0;;18241:2:1;83747:64:0::1;::::0;::::1;18223:21:1::0;18280:2;18260:18;;;18253:30;-1:-1:-1;;;18299:18:1;;;18292:51;18360:18;;83747:64:0::1;18039:345:1::0;83747:64:0::1;83846:15;83824:19;83899:38;83915:8:::0;83846:15;83899::::1;:38::i;:::-;83872:65;;83948:19;83996:16;83970:8;:23;;;:42;:87;;84041:16;83970:87;;;84015:8;:23;;;83970:87;83948:109;;84089:11;84076:9;:24;;84068:64;;;::::0;-1:-1:-1;;;84068:64:0;;18591:2:1;84068:64:0::1;::::0;::::1;18573:21:1::0;18630:2;18610:18;;;18603:30;18669:29;18649:18;;;18642:57;18716:18;;84068:64:0::1;18389:351:1::0;84068:64:0::1;84165:20:::0;;84200:21;;::::1;84196:307;;;84238:13;84254:21;84266:9:::0;84254;:21:::1;:::i;:::-;84238:37;;84323:5;84298:21;84308:10;84298:9;:21::i;:::-;:30;;84290:75;;;::::0;-1:-1:-1;;;84290:75:0;;18947:2:1;84290:75:0::1;::::0;::::1;18929:21:1::0;;;18966:18;;;18959:30;19025:34;19005:18;;;18998:62;19077:18;;84290:75:0::1;18745:356:1::0;84290:75:0::1;84380:34;84390:10;84402:4;84408:5;84380:9;:34::i;:::-;84434:57;::::0;;11679:25:1;;;84475:15:0::1;11735:2:1::0;11720:18;;11713:34;-1:-1:-1;;;;;84434:57:0;::::1;::::0;::::1;::::0;11652:18:1;84434:57:0::1;;;;;;;84223:280;84196:307;84515:32:::0;;;84575:14:::1;::::0;84538:9;;84575:26:::1;::::0;84592:9;;84575:26:::1;:::i;:::-;:38;;;;:::i;:::-;84558:14;:55:::0;84693:34:::1;84722:4:::0;84693:28:::1;:34::i;:::-;84743:57;::::0;;11679:25:1;;;84784:15:0::1;11735:2:1::0;11720:18;;11713:34;-1:-1:-1;;;;;84743:57:0;::::1;::::0;::::1;::::0;11652:18:1;84743:57:0::1;11505:248:1::0;38339:147:0;38425:4;38449:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;38449:29:0;;;;;;;;;;;;;;;38339:147::o;92772:962::-;-1:-1:-1;;;;;92890:26:0;;92832:7;92890:26;;;:20;:26;;;;;92832:7;;92963:733;92987:16;;92983:20;;92963:733;;;93025:32;93060:9;93070:1;93060:12;;;;;;;;:::i;:::-;;;;;;;;;;;;;;93092:17;;;;93060:12;;-1:-1:-1;93092:17:0;;93087:67;;93130:8;;;93087:67;93239:16;;;;93190:15;;93224:31;;93220:80;;93276:8;;;;93220:80;93314:19;93336:38;93352:8;93362:11;93336:15;:38::i;:::-;93412:23;;;;93314:60;;-1:-1:-1;93389:20:0;93472:26;;;:55;;93515:12;93472:55;;;93501:11;93472:55;93450:77;;93542:20;93588:11;93565:8;:20;;;:34;:77;;93641:1;93565:77;;;93603:20;;:34;;93626:11;;93603:34;:::i;:::-;93542:100;-1:-1:-1;93657:27:0;93542:100;93657:27;;:::i;:::-;;;93010:686;;;;;;92963:733;93005:3;;92963:733;;84949:507;24283:13;:11;:13::i;:::-;34332:21:::1;:19;:21::i;:::-;-1:-1:-1::0;;;;;85072:26:0;::::2;;::::0;;;:20:::2;:26;::::0;;;;:33;85064:41;::::2;85056:76;;;;-1:-1:-1::0;;;85056:76:0::2;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;85178:26:0;::::2;85143:32;85178:26:::0;;;:20:::2;:26;::::0;;;;:33;;85205:5;;85178:33;::::2;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;::::2;::::0;;::::2;;85230:17;::::0;::::2;::::0;85178:33;;-1:-1:-1;85230:17:0::2;;85222:56;;;;-1:-1:-1::0;;;85222:56:0::2;;;;;;;:::i;:::-;85289:17;::::0;::::2;:25:::0;;-1:-1:-1;;85289:25:0::2;::::0;;85399:49:::2;::::0;85432:15:::2;1549:25:1::0;;-1:-1:-1;;;;;85399:49:0;::::2;::::0;::::2;::::0;1537:2:1;1522:18;85399:49:0::2;1403:177:1::0;48156:104:0;48212:13;48245:7;48238:14;;;;;:::i;93895:802::-;-1:-1:-1;;;;;94258:26:0;;94017:19;94258:26;;;:20;:26;;;;;94299:16;;94017:19;;;;;;;;;;94258:26;94299:21;;94295:87;;94345:1;94348;94351;94354;94357:5;94364;94337:33;;;;;;;;;;;;;;;94295:87;94437:16;;94392:32;;94427:9;;94437:20;;94456:1;;94437:20;:::i;:::-;94427:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;94491:20;;94526:23;;;;94564:18;;;;94597:16;;;;94628:17;;;;;94491:20;;-1:-1:-1;94526:23:0;;-1:-1:-1;94564:18:0;-1:-1:-1;94597:16:0;;-1:-1:-1;94628:17:0;;;;;-1:-1:-1;94628:17:0;94660:18;;;;;-1:-1:-1;;;93895:802:0;;;;;;;;:::o;52489:436::-;52582:4;751:10;52582:4;52665:25;751:10;52682:7;52665:9;:25::i;:::-;52638:52;;52729:15;52709:16;:35;;52701:85;;;;-1:-1:-1;;;52701:85:0;;19308:2:1;52701:85:0;;;19290:21:1;19347:2;19327:18;;;19320:30;19386:34;19366:18;;;19359:62;-1:-1:-1;;;19437:18:1;;;19430:35;19482:19;;52701:85:0;19106:401:1;52701:85:0;52822:60;52831:5;52838:7;52866:15;52847:16;:34;52822:8;:60::i;65781:338::-;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;65864:21:0;::::1;65856:49;;;;-1:-1:-1::0;;;65856:49:0::1;;;;;;;:::i;:::-;65916:35;-1:-1:-1::0;;;;;;;;;;;65943:7:0::1;65916:11;:35::i;:::-;-1:-1:-1::0;;;;;66025:26:0;::::1;66054:5;66025:26:::0;;;:17:::1;:26;::::0;;;;;:34;;-1:-1:-1;;66025:34:0::1;::::0;;66075:36;66100:10:::1;::::0;66025:26;66075:36:::1;::::0;::::1;65781:338:::0;:::o;49570:193::-;49649:4;751:10;49705:28;751:10;49722:2;49726:6;49705:9;:28::i;89308:2175::-;-1:-1:-1;;;;;89416:26:0;;89378:35;89416:26;;;:20;:26;;;;;;89455:1952;89479:16;;89475:20;;89455:1952;;;89517:32;89552:9;89562:1;89552:12;;;;;;;;:::i;:::-;;;;;;;;;;;;;;89586:17;;;;89552:12;;-1:-1:-1;89586:17:0;;89585:18;;:45;;-1:-1:-1;89607:18:0;;;;:23;89585:45;89581:94;;;89651:8;;;89581:94;89820:16;;;;89771:15;;89805:31;;89801:593;;89887:20;;89861:23;;;;:46;89857:358;;;89976:23;;;;89953:20;;89932:18;;89953:46;;;:::i;:::-;90048:20;;90022:23;;;:46;90091:13;:27;;89932:67;;-1:-1:-1;89932:67:0;;90048:20;;90091:27;;89932:67;;90091:27;:::i;:::-;;;;-1:-1:-1;;90146:49:0;;;11679:25:1;;;90179:15:0;11735:2:1;11720:18;;11713:34;-1:-1:-1;;;;;90146:49:0;;;;;11652:18:1;90146:49:0;;;;;;;89909:306;89857:358;90233:17;;;:25;;-1:-1:-1;;90233:25:0;;;90313:20;;90282:69;;;11679:25:1;;;90335:15:0;11735:2:1;11720:18;;11713:34;-1:-1:-1;;;;;90282:69:0;;;;;11652:18:1;90282:69:0;;;;;;;90370:8;;;;89801:593;90408:25;90436:38;90452:8;90462:11;90436:15;:38::i;:::-;90408:66;;90515:8;:23;;;90495:17;:43;90491:618;;;90559:26;90608:8;:23;;;90588:17;:43;;;;:::i;:::-;90559:72;;90676:17;90650:8;:23;;:43;;;;90729:18;90712:13;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;;90773:57:0;;;11679:25:1;;;90814:15:0;11735:2:1;11720:18;;11713:34;-1:-1:-1;;;;;90773:57:0;;;;;11652:18:1;90773:57:0;;;;;;;90540:306;90491:618;;;90876:8;:23;;;90856:17;:43;90852:257;;;91033:23;;;;90998:95;;;14540:25:1;;;14596:2;14581:18;;14574:34;;;91077:15:0;14624:18:1;;;14617:34;-1:-1:-1;;;;;90998:95:0;;;;;14528:2:1;14513:18;90998:95:0;;;;;;;90852:257;91200:20;;91179:41;;;;;:62;;-1:-1:-1;91224:17:0;;;;;;91179:62;91175:221;;;91262:17;;;:25;;-1:-1:-1;;91262:25:0;;;91342:20;;91311:69;;;11679:25:1;;;91364:15:0;11735:2:1;11720:18;;11713:34;-1:-1:-1;;;;;91311:69:0;;;;;11652:18:1;91311:69:0;;;;;;;91175:221;89502:1905;;;89455:1952;89497:3;;89455:1952;;98965:233;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;99053:23:0;::::1;99045:58;;;;-1:-1:-1::0;;;99045:58:0::1;;;;;;;:::i;:::-;99114:15;:27:::0;;-1:-1:-1;;;;;;99114:27:0::1;-1:-1:-1::0;;;;;99114:27:0;::::1;::::0;;::::1;::::0;;;99157:33:::1;::::0;4433:51:1;;;99157:33:0::1;::::0;4421:2:1;4406:18;99157:33:0::1;4287:203:1::0;67894:685:0;-1:-1:-1;;;;;67985:22:0;;67961:7;67985:22;;;:13;:22;;;;;;;;67981:591;;;-1:-1:-1;;;;;49338:18:0;;68118:20;49338:18;;;;;;;;;;;;68203:24;49338:18;68203:15;:24::i;:::-;68180:47;-1:-1:-1;68402:27:0;68180:47;68402:12;:27;:::i;:::-;68395:34;67894:685;-1:-1:-1;;;;67894:685:0:o;67981:591::-;-1:-1:-1;;;;;49338:18:0;;49311:7;49338:18;;;;;;;;;;;68536:24;49237:127;67981:591;67894:685;;;:::o;85664:1085::-;24283:13;:11;:13::i;:::-;34332:21:::1;:19;:21::i;:::-;-1:-1:-1::0;;;;;85787:26:0;::::2;;::::0;;;:20:::2;:26;::::0;;;;:33;85779:41;::::2;85771:76;;;;-1:-1:-1::0;;;85771:76:0::2;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;85893:26:0;::::2;85858:32;85893:26:::0;;;:20:::2;:26;::::0;;;;:33;;85920:5;;85893:33;::::2;;;;;:::i;:::-;;;;;;;;;;;85858:68;;85946:8;:20;;;;;;;;;;;;85945:21;85937:60;;;::::0;-1:-1:-1;;;85937:60:0;;19714:2:1;85937:60:0::2;::::0;::::2;19696:21:1::0;19753:2;19733:18;;;19726:30;19792:28;19772:18;;;19765:56;19838:18;;85937:60:0::2;19512:350:1::0;85937:60:0::2;86017:17;::::0;::::2;::::0;::::2;;86016:18;86008:65;;;::::0;-1:-1:-1;;;86008:65:0;;20069:2:1;86008:65:0::2;::::0;::::2;20051:21:1::0;20108:2;20088:18;;;20081:30;20147:34;20127:18;;;20120:62;-1:-1:-1;;;20198:18:1;;;20191:32;20240:19;;86008:65:0::2;19867:398:1::0;86008:65:0::2;86092:8;:18;;;86114:1;86092:23:::0;86084:62:::2;;;::::0;-1:-1:-1;;;86084:62:0;;20472:2:1;86084:62:0::2;::::0;::::2;20454:21:1::0;20511:2;20491:18;;;20484:30;20550:28;20530:18;;;20523:56;20596:18;;86084:62:0::2;20270:350:1::0;86084:62:0::2;86159:24;86186:42;86202:8;86212:15;86186;:42::i;:::-;86159:69;;86239:21;86289:16;86263:8;:23;;;:42;:87;;86334:16;86263:87;;;86308:8;:23;;;86263:87;86239:111;;86361:23;86410:13;86387:8;:20;;;:36;:81;;86467:1;86387:81;;;86427:20:::0;;:36:::2;::::0;86450:13;;86427:36:::2;:::i;:::-;86361:107;;86516:15;86487:25;86507:4;86487:19;:25::i;:::-;:44;;86479:91;;;::::0;-1:-1:-1;;;86479:91:0;;20827:2:1;86479:91:0::2;::::0;::::2;20809:21:1::0;20866:2;20846:18;;;20839:30;20905:34;20885:18;;;20878:62;-1:-1:-1;;;20956:18:1;;;20949:32;20998:19;;86479:91:0::2;20625:398:1::0;86479:91:0::2;86583:17;::::0;::::2;:24:::0;;-1:-1:-1;;86583:24:0::2;86603:4;86583:24;::::0;;86692:49:::2;::::0;-1:-1:-1;;;;;86692:49:0;::::2;::::0;::::2;::::0;::::2;::::0;86725:15:::2;1549:25:1::0;;1537:2;1522:18;;1403:177;86692:49:0::2;;;;;;;;85760:989;;;;34376:20:::1;33770:1:::0;34896:7;:22;34713:213;66534:128;66599:4;66623:31;-1:-1:-1;;;;;;;;;;;66646:7:0;66623;:31::i;40747:149::-;39940:7;39967:12;;;:6;:12;;;;;:22;;;37935:16;37946:4;37935:10;:16::i;:::-;40862:26:::1;40874:4;40880:7;40862:11;:26::i;91613:590::-:0;-1:-1:-1;;;;;91731:26:0;;91673:7;91731:26;;;:20;:26;;;;;91673:7;;91808:353;91832:16;;91828:20;;91808:353;;;91870:32;91905:9;91915:1;91905:12;;;;;;;;:::i;:::-;;;;;;;;;;;;;;91937:17;;;;91905:12;;-1:-1:-1;91937:17:0;;91936:18;;:45;;-1:-1:-1;91958:18:0;;;;:23;91936:45;91932:94;;;92002:8;;;91932:94;92062:15;92111:38;92127:8;92062:15;92111;:38::i;:::-;92092:57;;;;:::i;:::-;;;91855:306;;91808:353;91850:3;;91808:353;;49826:151;-1:-1:-1;;;;;49942:18:0;;;49915:7;49942:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;49826:151::o;98032:278::-;24283:13;:11;:13::i;:::-;98177:15:::1;;98165:8;;98155:7;98137:15;;98116:18;;:36;;;;:::i;:::-;:46;;;;:::i;:::-;:57;;;;:::i;:::-;:76;;98108:115;;;;-1:-1:-1::0;;;98108:115:0::1;;;;;;;:::i;:::-;98234:13;:23:::0;;;98273:29:::1;::::0;1549:25:1;;;98273:29:0::1;::::0;1537:2:1;1522:18;98273:29:0::1;1403:177:1::0;101966:782:0;102102:25;;;;102209:30;;;102201:65;;;;-1:-1:-1;;;102201:65:0;;16383:2:1;102201:65:0;;;16365:21:1;16422:2;16402:18;;;16395:30;-1:-1:-1;;;16441:18:1;;;16434:52;16503:18;;102201:65:0;16181:346:1;102201:65:0;-1:-1:-1;102299:1:0;;-1:-1:-1;102299:1:0;;102340:216;102360:18;;;102340:216;;;102424:1;102404:5;;102410:1;102404:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;102404:22:0;;;:40;;;;;102443:1;102430:7;;102438:1;102430:10;;;;;;;:::i;:::-;;;;;;;:14;102404:40;102400:145;;;102486:7;;102494:1;102486:10;;;;;;;:::i;:::-;;;;;;;102465:31;;;;;:::i;:::-;;-1:-1:-1;102515:14:0;;;;:::i;:::-;;;;102400:145;102380:3;;102340:216;;;;102583:21;102593:10;102583:9;:21::i;:::-;102568:36;;102644:17;102628:12;:33;;102615:46;;101966:782;;;;;;;;;:::o;99263:239::-;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;99353:23:0;::::1;99345:58;;;;-1:-1:-1::0;;;99345:58:0::1;;;;;;;:::i;:::-;99414:17;:29:::0;;-1:-1:-1;;;;;;99414:29:0::1;-1:-1:-1::0;;;;;99414:29:0;::::1;::::0;;::::1;::::0;;;99459:35:::1;::::0;4433:51:1;;;99459:35:0::1;::::0;4421:2:1;4406:18;99459:35:0::1;4287:203:1::0;44880:181:0;24283:13;:11;:13::i;:::-;44970::::1;:24:::0;;-1:-1:-1;;;;;44970:24:0;::::1;-1:-1:-1::0;;;;;;44970:24:0;;::::1;::::0;::::1;::::0;;;45035:7:::1;24470:6:::0;;-1:-1:-1;;;;;24470:6:0;;24397:87;45035:7:::1;-1:-1:-1::0;;;;;45010:43:0::1;;;;;;;;;;;44880:181:::0;:::o;98690:212::-;24283:13;:11;:13::i;:::-;-1:-1:-1;;;;;98771:23:0;::::1;98763:58;;;;-1:-1:-1::0;;;98763:58:0::1;;;;;;;:::i;:::-;98832:8;:20:::0;;-1:-1:-1;;;;;;98832:20:0::1;-1:-1:-1::0;;;;;98832:20:0;::::1;::::0;;::::1;::::0;;;98868:26:::1;::::0;4433:51:1;;;98868:26:0::1;::::0;4421:2:1;4406:18;98868:26:0::1;4287:203:1::0;56482:346:0;-1:-1:-1;;;;;56584:19:0;;56576:68;;;;-1:-1:-1;;;56576:68:0;;21370:2:1;56576:68:0;;;21352:21:1;21409:2;21389:18;;;21382:30;21448:34;21428:18;;;21421:62;-1:-1:-1;;;21499:18:1;;;21492:34;21543:19;;56576:68:0;21168:400:1;56576:68:0;-1:-1:-1;;;;;56663:21:0;;56655:68;;;;-1:-1:-1;;;56655:68:0;;21775:2:1;56655:68:0;;;21757:21:1;21814:2;21794:18;;;21787:30;21853:34;21833:18;;;21826:62;-1:-1:-1;;;21904:18:1;;;21897:32;21946:19;;56655:68:0;21573:398:1;56655:68:0;-1:-1:-1;;;;;56736:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;56788:32;;1549:25:1;;;56788:32:0;;1522:18:1;56788:32:0;;;;;;;56482:346;;;:::o;24562:132::-;24470:6;;-1:-1:-1;;;;;24470:6:0;751:10;24626:23;24618:68;;;;-1:-1:-1;;;24618:68:0;;22178:2:1;24618:68:0;;;22160:21:1;;;22197:18;;;22190:30;22256:34;22236:18;;;22229:62;22308:18;;24618:68:0;21976:356:1;34412:293:0;33814:1;34546:7;;:19;34538:63;;;;-1:-1:-1;;;34538:63:0;;22539:2:1;34538:63:0;;;22521:21:1;22578:2;22558:18;;;22551:30;22617:33;22597:18;;;22590:61;22668:18;;34538:63:0;22337:355:1;34538:63:0;33814:1;34679:7;:18;34412:293::o;77704:257::-;-1:-1:-1;;;;;77819:26:0;;77771:8;77819:26;;;:20;:26;;;;;:33;77771:8;;77867;;;77863:58;;-1:-1:-1;77900:5:0;;;;-1:-1:-1;77704:257:0;-1:-1:-1;;77704:257:0:o;77863:58::-;77939:4;77945:7;77939:4;77945:3;:7;:::i;:::-;77931:22;;;;;77704:257;;;:::o;78152:2182::-;78253:7;78289:8;:18;;;78277:9;:30;78273:71;;;-1:-1:-1;78331:1:0;78324:8;;78273:71;78371:8;:16;;;78358:9;:29;78354:89;;-1:-1:-1;78411:20:0;;78404:27;;78354:89;78455:22;78492:8;:18;;;78480:9;:30;;;;:::i;:::-;78455:55;-1:-1:-1;78521:24:0;78548:36;78566:17;78455:55;78548:36;:::i;:::-;78521:63;;78618:1;78599:16;:20;78595:61;;;78643:1;78636:8;;;;;;78595:61;78668:19;;78815:1;78795:21;;78791:45;;78818:18;;;;:::i;:::-;;;;78791:45;78871:2;78851:16;:22;78847:46;;78875:18;;;;:::i;:::-;;;;78847:46;78928:2;78908:16;:22;78904:46;;78932:18;;;;:::i;:::-;;;;78904:46;78985:2;78965:16;:22;78961:46;;78989:18;;;;:::i;:::-;;;;78961:46;79042:2;79022:16;:22;79018:46;;79046:18;;;;:::i;:::-;;;;79018:46;79075:23;79157:4;60719:2;79102:8;:20;;;:51;;;;:::i;:::-;79101:60;;;;:::i;:::-;79075:86;-1:-1:-1;79187:34:0;79205:16;79075:86;79187:34;:::i;:::-;79172:49;;;;:::i;:::-;;;79311:2;79291:16;:22;79287:420;;79330:21;79391:2;79370:173;79404:2;79395:5;:11;79370:173;;79463:5;79443:16;:25;79439:89;;79493:15;;;;:::i;:::-;;;;79439:89;79408:10;79417:1;79408:10;;:::i;:::-;;;79370:173;;;;79557:20;79633:4;60798:2;79581:8;:20;;;:48;;;;:::i;:::-;79580:57;;;;:::i;:::-;79557:80;-1:-1:-1;79667:28:0;79682:13;79557:80;79667:28;:::i;:::-;79652:43;;;;:::i;:::-;;;79315:392;;79287:420;79796:2;79776:16;:22;79772:413;;79815:20;79875:2;79854:172;79888:2;79879:5;:11;79854:172;;79947:5;79927:16;:25;79923:88;;79977:14;;;;:::i;:::-;;;;79923:88;79892:10;79901:1;79892:10;;:::i;:::-;;;79854:172;;;;80040:19;80113:4;60873:2;80063:8;:20;;;:46;;;;:::i;:::-;80062:55;;;;:::i;:::-;80040:77;-1:-1:-1;80147:26:0;80161:12;80040:77;80147:26;:::i;:::-;80132:41;;;;:::i;:::-;;;79800:385;;79772:413;80215:20;;80201:34;;80197:101;;;80266:20;;;-1:-1:-1;80197:101:0;-1:-1:-1;80315:11:0;;78152:2182;-1:-1:-1;;;;;;78152:2182:0:o;57119:419::-;57220:24;57247:25;57257:5;57264:7;57247:9;:25::i;:::-;57220:52;;-1:-1:-1;;57287:16:0;:37;57283:248;;57369:6;57349:16;:26;;57341:68;;;;-1:-1:-1;;;57341:68:0;;22899:2:1;57341:68:0;;;22881:21:1;22938:2;22918:18;;;22911:30;22977:31;22957:18;;;22950:59;23026:18;;57341:68:0;22697:353:1;57341:68:0;57453:51;57462:5;57469:7;57497:6;57478:16;:25;57453:8;:51::i;:::-;57209:329;57119:419;;;:::o;68669:1623::-;30653:19;:17;:19::i;:::-;-1:-1:-1;;;;;68789:18:0;::::1;68781:68;;;;-1:-1:-1::0;;;68781:68:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;68868:16:0;::::1;68860:64;;;;-1:-1:-1::0;;;68860:64:0::1;;;;;;;:::i;:::-;68952:1;68943:6;:10;68935:64;;;::::0;-1:-1:-1;;;68935:64:0;;24067:2:1;68935:64:0::1;::::0;::::1;24049:21:1::0;24106:2;24086:18;;;24079:30;24145:34;24125:18;;;24118:62;-1:-1:-1;;;24196:18:1;;;24189:39;24245:19;;68935:64:0::1;23865:405:1::0;68935:64:0::1;-1:-1:-1::0;;;;;69096:19:0;::::1;;::::0;;;:13:::1;:19;::::0;;;;;::::1;;69092:86;;;69132:34;69161:4;69132:28;:34::i;:::-;-1:-1:-1::0;;;;;69192:17:0;::::1;;::::0;;;:13:::1;:17;::::0;;;;;::::1;;69188:82;;;69226:32;69255:2;69226:28;:32::i;:::-;69321:20;69344:25;69364:4;69344:19;:25::i;:::-;69321:48;;69404:6;69388:12;:22;;69380:68;;;::::0;-1:-1:-1;;;69380:68:0;;24477:2:1;69380:68:0::1;::::0;::::1;24459:21:1::0;24516:2;24496:18;;;24489:30;24555:34;24535:18;;;24528:62;-1:-1:-1;;;24606:18:1;;;24599:31;24647:19;;69380:68:0::1;24275:397:1::0;69380:68:0::1;-1:-1:-1::0;;;;;69524:25:0;::::1;;::::0;;;:19:::1;:25;::::0;;;;;::::1;;69523:26;:54:::0;::::1;;;-1:-1:-1::0;;;;;;69554:23:0;::::1;;::::0;;;:19:::1;:23;::::0;;;;;::::1;;69553:24;69523:54;69519:166;;;69612:11;;69602:6;:21;;69594:79;;;::::0;-1:-1:-1;;;69594:79:0;;24879:2:1;69594:79:0::1;::::0;::::1;24861:21:1::0;24918:2;24898:18;;;24891:30;24957:34;24937:18;;;24930:62;-1:-1:-1;;;25008:18:1;;;25001:43;25061:19;;69594:79:0::1;24677:409:1::0;69594:79:0::1;69759:15;::::0;69723:17:::1;::::0;69759:19;;;;:47:::1;;-1:-1:-1::0;;;;;;69783:23:0;::::1;;::::0;;;:17:::1;:23;::::0;;;;;::::1;;69782:24;69759:47;:73;;;;-1:-1:-1::0;;;;;;69811:21:0;::::1;;::::0;;;:17:::1;:21;::::0;;;;;::::1;;69810:22;69759:73;69755:162;;;59592:4;69871:15;;69862:6;:24;;;;:::i;:::-;69861:44;;;;:::i;:::-;69849:56;;69755:162;69929:22;69954:18;69963:9:::0;69954:6;:18:::1;:::i;:::-;69929:43;;70045:41;70061:4;70067:2;70071:14;70045:15;:41::i;:::-;70154:13:::0;;70150:135:::1;;70184:47;70200:4;70214;70221:9;70184:15;:47::i;:::-;70246:27;70263:9;70246:16;:27::i;:::-;68770:1522;;;68669:1623:::0;;;:::o;38790:105::-;38857:30;38868:4;751:10;38857;:30::i;43048:238::-;43132:22;43140:4;43146:7;43132;:22::i;:::-;43127:152;;43171:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;43171:29:0;;;;;;;;;:36;;-1:-1:-1;;43171:36:0;43203:4;43171:36;;;43254:12;751:10;;671:98;43254:12;-1:-1:-1;;;;;43227:40:0;43245:7;-1:-1:-1;;;;;43227:40:0;43239:4;43227:40;;;;;;;;;;43048:238;;:::o;43466:239::-;43550:22;43558:4;43564:7;43550;:22::i;:::-;43546:152;;;43621:5;43589:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;43589:29:0;;;;;;;;;;:37;;-1:-1:-1;;43589:37:0;;;43646:40;751:10;;43589:12;;43646:40;;43621:5;43646:40;43466:239;;:::o;31903:120::-;30912:16;:14;:16::i;:::-;31962:7:::1;:15:::0;;-1:-1:-1;;31962:15:0::1;::::0;;31993:22:::1;751:10:::0;32002:12:::1;31993:22;::::0;-1:-1:-1;;;;;4451:32:1;;;4433:51;;4421:2;4406:18;31993:22:0::1;;;;;;;31903:120::o:0;53395:806::-;-1:-1:-1;;;;;53492:18:0;;53484:68;;;;-1:-1:-1;;;53484:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;53571:16:0;;53563:64;;;;-1:-1:-1;;;53563:64:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;53713:15:0;;53691:19;53713:15;;;;;;;;;;;53747:21;;;;53739:72;;;;-1:-1:-1;;;53739:72:0;;25293:2:1;53739:72:0;;;25275:21:1;25332:2;25312:18;;;25305:30;25371:34;25351:18;;;25344:62;-1:-1:-1;;;25422:18:1;;;25415:36;25468:19;;53739:72:0;25091:402:1;53739:72:0;-1:-1:-1;;;;;53847:15:0;;;:9;:15;;;;;;;;;;;53865:20;;;53847:38;;54065:13;;;;;;;;;;:23;;;;;;54117:26;;1549:25:1;;;54065:13:0;;54117:26;;1522:18:1;54117:26:0;;;;;;;54156:37;40307:147;45251:156;45341:13;45334:20;;-1:-1:-1;;;;;;45334:20:0;;;45365:34;45390:8;45365:24;:34::i;31207:108::-;31119:7;;;;31277:9;31269:38;;;;-1:-1:-1;;;31269:38:0;;25700:2:1;31269:38:0;;;25682:21:1;25739:2;25719:18;;;25712:30;-1:-1:-1;;;25758:18:1;;;25751:46;25814:18;;31269:38:0;25498:340:1;31644:118:0;30653:19;:17;:19::i;:::-;31704:7:::1;:14:::0;;-1:-1:-1;;31704:14:0::1;31714:4;31704:14;::::0;;31734:20:::1;31741:12;751:10:::0;;671:98;70378:1605;70507:9;70520:1;70507:14;70503:53;;70378:1605;:::o;70503:53::-;70645:18;;70591:9;;70645:22;70641:284;;70684:16;70738:15;;70716:18;;70704:9;:30;;;;:::i;:::-;70703:50;;;;:::i;:::-;70684:69;-1:-1:-1;70772:12:0;;70768:146;;70836:8;;70805:50;;70829:4;;-1:-1:-1;;;;;70836:8:0;70846;70805:15;:50::i;:::-;70874:24;70890:8;70874:24;;:::i;:::-;;;70768:146;70669:256;70641:284;70969:15;;:19;70965:323;;71005:25;71065:15;;71046;;71034:9;:27;;;;:::i;:::-;71033:47;;;;:::i;:::-;71005:75;-1:-1:-1;71099:21:0;;71095:182;;71172:17;;71141:68;;71165:4;;-1:-1:-1;;;;;71172:17:0;71191;71141:15;:68::i;:::-;71228:33;71244:17;71228:33;;:::i;:::-;;;71095:182;70990:298;70965:323;71326:13;;:17;71322:309;;71360:23;71416:15;;71399:13;;71387:9;:25;;;;:::i;:::-;71386:45;;;;:::i;:::-;71360:71;-1:-1:-1;71450:19:0;;71446:174;;71521:15;;71490:64;;71514:4;;-1:-1:-1;;;;;71521:15:0;71538;71490;:64::i;:::-;71573:31;71589:15;71573:31;;:::i;:::-;;;71446:174;71345:286;71322:309;71680:16;;71676:300;;71717:8;;:12;71713:252;;71750:34;71764:4;71771:12;71750:5;:34::i;71713:252::-;71920:14;;71889:60;;71913:4;;-1:-1:-1;;;;;71920:14:0;71936:12;71889:15;:60::i;39185:492::-;39274:22;39282:4;39288:7;39274;:22::i;:::-;39269:401;;39462:28;39482:7;39462:19;:28::i;:::-;39563:38;39591:4;39598:2;39563:19;:38::i;:::-;39367:257;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;39367:257:0;;;;;;;;;;-1:-1:-1;;;39313:345:0;;;;;;;:::i;31392:108::-;31119:7;;;;31451:41;;;;-1:-1:-1;;;31451:41:0;;26862:2:1;31451:41:0;;;26844:21:1;26901:2;26881:18;;;26874:30;-1:-1:-1;;;26920:18:1;;;26913:50;26980:18;;31451:41:0;26660:344:1;25657:191:0;25750:6;;;-1:-1:-1;;;;;25767:17:0;;;-1:-1:-1;;;;;;25767:17:0;;;;;;;25800:40;;25750:6;;;25767:17;25750:6;;25800:40;;25731:16;;25800:40;25720:128;25657:191;:::o;55369:675::-;-1:-1:-1;;;;;55453:21:0;;55445:67;;;;-1:-1:-1;;;55445:67:0;;27211:2:1;55445:67:0;;;27193:21:1;27250:2;27230:18;;;27223:30;27289:34;27269:18;;;27262:62;-1:-1:-1;;;27340:18:1;;;27333:31;27381:19;;55445:67:0;27009:397:1;55445:67:0;-1:-1:-1;;;;;55612:18:0;;55587:22;55612:18;;;;;;;;;;;55649:24;;;;55641:71;;;;-1:-1:-1;;;55641:71:0;;27613:2:1;55641:71:0;;;27595:21:1;27652:2;27632:18;;;27625:30;27691:34;27671:18;;;27664:62;-1:-1:-1;;;27742:18:1;;;27735:32;27784:19;;55641:71:0;27411:398:1;55641:71:0;-1:-1:-1;;;;;55748:18:0;;:9;:18;;;;;;;;;;;55769:23;;;55748:44;;55887:12;:22;;;;;;;55938:37;1549:25:1;;;55748:9:0;;:18;55938:37;;1522:18:1;55938:37:0;;;;;;;40307:147;;;:::o;19772:151::-;19830:13;19863:52;-1:-1:-1;;;;;19875:22:0;;17647:2;19168:447;19243:13;19269:19;19301:10;19305:6;19301:1;:10;:::i;:::-;:14;;19314:1;19301:14;:::i;:::-;19291:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19291:25:0;;19269:47;;-1:-1:-1;;;19327:6:0;19334:1;19327:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;19327:15:0;;;;;;;;;-1:-1:-1;;;19353:6:0;19360:1;19353:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;19353:15:0;;;;;;;;-1:-1:-1;19384:9:0;19396:10;19400:6;19396:1;:10;:::i;:::-;:14;;19409:1;19396:14;:::i;:::-;19384:26;;19379:131;19416:1;19412;:5;19379:131;;;-1:-1:-1;;;19460:5:0;19468:3;19460:11;19451:21;;;;;;;:::i;:::-;;;;19439:6;19446:1;19439:9;;;;;;;;:::i;:::-;;;;:33;-1:-1:-1;;;;;19439:33:0;;;;;;;;-1:-1:-1;19497:1:0;19487:11;;;;;19419:3;;;:::i;:::-;;;19379:131;;;-1:-1:-1;19528:10:0;;19520:55;;;;-1:-1:-1;;;19520:55:0;;28289:2:1;19520:55:0;;;28271:21:1;;;28308:18;;;28301:30;28367:34;28347:18;;;28340:62;28419:18;;19520:55:0;28087:356:1;19520:55:0;19600:6;19168:447;-1:-1:-1;;;19168:447:0:o;14:286:1:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:1;;209:43;;199:71;;266:1;263;256:12;497:418;646:2;635:9;628:21;609:4;678:6;672:13;721:6;716:2;705:9;701:18;694:34;780:6;775:2;767:6;763:15;758:2;747:9;743:18;737:50;836:1;831:2;822:6;811:9;807:22;803:31;796:42;906:2;899;895:7;890:2;882:6;878:15;874:29;863:9;859:45;855:54;847:62;;;497:418;;;;:::o;920:173::-;988:20;;-1:-1:-1;;;;;1037:31:1;;1027:42;;1017:70;;1083:1;1080;1073:12;1098:300;1166:6;1174;1227:2;1215:9;1206:7;1202:23;1198:32;1195:52;;;1243:1;1240;1233:12;1195:52;1266:29;1285:9;1266:29;:::i;:::-;1256:39;1364:2;1349:18;;;;1336:32;;-1:-1:-1;;;1098:300:1:o;1585:347::-;1650:6;1658;1711:2;1699:9;1690:7;1686:23;1682:32;1679:52;;;1727:1;1724;1717:12;1679:52;1750:29;1769:9;1750:29;:::i;:::-;1740:39;;1829:2;1818:9;1814:18;1801:32;1876:5;1869:13;1862:21;1855:5;1852:32;1842:60;;1898:1;1895;1888:12;1842:60;1921:5;1911:15;;;1585:347;;;;;:::o;1937:637::-;2127:2;2139:21;;;2209:13;;2112:18;;;2231:22;;;2079:4;;2310:15;;;2284:2;2269:18;;;2079:4;2353:195;2367:6;2364:1;2361:13;2353:195;;;2432:13;;-1:-1:-1;;;;;2428:39:1;2416:52;;2497:2;2523:15;;;;2488:12;;;;2464:1;2382:9;2353:195;;;-1:-1:-1;2565:3:1;;1937:637;-1:-1:-1;;;;;1937:637:1:o;2579:186::-;2638:6;2691:2;2679:9;2670:7;2666:23;2662:32;2659:52;;;2707:1;2704;2697:12;2659:52;2730:29;2749:9;2730:29;:::i;2770:374::-;2847:6;2855;2863;2916:2;2904:9;2895:7;2891:23;2887:32;2884:52;;;2932:1;2929;2922:12;2884:52;2955:29;2974:9;2955:29;:::i;:::-;2945:39;;3003:38;3037:2;3026:9;3022:18;3003:38;:::i;:::-;2770:374;;2993:48;;-1:-1:-1;;;3110:2:1;3095:18;;;;3082:32;;2770:374::o;3149:226::-;3208:6;3261:2;3249:9;3240:7;3236:23;3232:32;3229:52;;;3277:1;3274;3267:12;3229:52;-1:-1:-1;3322:23:1;;3149:226;-1:-1:-1;3149:226:1:o;3793:300::-;3861:6;3869;3922:2;3910:9;3901:7;3897:23;3893:32;3890:52;;;3938:1;3935;3928:12;3890:52;3983:23;;;-1:-1:-1;4049:38:1;4083:2;4068:18;;4049:38;:::i;:::-;4039:48;;3793:300;;;;;:::o;4495:420::-;4572:6;4580;4588;4641:2;4629:9;4620:7;4616:23;4612:32;4609:52;;;4657:1;4654;4647:12;4609:52;4680:29;4699:9;4680:29;:::i;:::-;4670:39;4778:2;4763:18;;4750:32;;-1:-1:-1;4879:2:1;4864:18;;;4851:32;;4495:420;-1:-1:-1;;;4495:420:1:o;5660:367::-;5723:8;5733:6;5787:3;5780:4;5772:6;5768:17;5764:27;5754:55;;5805:1;5802;5795:12;5754:55;-1:-1:-1;5828:20:1;;5871:18;5860:30;;5857:50;;;5903:1;5900;5893:12;5857:50;5940:4;5932:6;5928:17;5916:29;;6000:3;5993:4;5983:6;5980:1;5976:14;5968:6;5964:27;5960:38;5957:47;5954:67;;;6017:1;6014;6007:12;5954:67;5660:367;;;;;:::o;6032:768::-;6154:6;6162;6170;6178;6231:2;6219:9;6210:7;6206:23;6202:32;6199:52;;;6247:1;6244;6237:12;6199:52;6287:9;6274:23;6320:18;6312:6;6309:30;6306:50;;;6352:1;6349;6342:12;6306:50;6391:70;6453:7;6444:6;6433:9;6429:22;6391:70;:::i;:::-;6480:8;;-1:-1:-1;6365:96:1;-1:-1:-1;;6568:2:1;6553:18;;6540:32;6597:18;6584:32;;6581:52;;;6629:1;6626;6619:12;6581:52;6668:72;6732:7;6721:8;6710:9;6706:24;6668:72;:::i;:::-;6032:768;;;;-1:-1:-1;6759:8:1;-1:-1:-1;;;;6032:768:1:o;8311:260::-;8379:6;8387;8440:2;8428:9;8419:7;8415:23;8411:32;8408:52;;;8456:1;8453;8446:12;8408:52;8479:29;8498:9;8479:29;:::i;:::-;8469:39;;8527:38;8561:2;8550:9;8546:18;8527:38;:::i;8982:380::-;9061:1;9057:12;;;;9104;;;9125:61;;9179:4;9171:6;9167:17;9157:27;;9125:61;9232:2;9224:6;9221:14;9201:18;9198:38;9195:161;;9278:10;9273:3;9269:20;9266:1;9259:31;9313:4;9310:1;9303:15;9341:4;9338:1;9331:15;9195:161;;8982:380;;;:::o;9367:346::-;9569:2;9551:21;;;9608:2;9588:18;;;9581:30;-1:-1:-1;;;9642:2:1;9627:18;;9620:52;9704:2;9689:18;;9367:346::o;9718:127::-;9779:10;9774:3;9770:20;9767:1;9760:31;9810:4;9807:1;9800:15;9834:4;9831:1;9824:15;9850:350;10052:2;10034:21;;;10091:2;10071:18;;;10064:30;10130:28;10125:2;10110:18;;10103:56;10191:2;10176:18;;9850:350::o;10757:127::-;10818:10;10813:3;10809:20;10806:1;10799:31;10849:4;10846:1;10839:15;10873:4;10870:1;10863:15;10889:128;10956:9;;;10977:11;;;10974:37;;;10991:18;;:::i;11022:125::-;11087:9;;;11108:10;;;11105:36;;;11121:18;;:::i;11758:350::-;11960:2;11942:21;;;11999:2;11979:18;;;11972:30;12038:28;12033:2;12018:18;;12011:56;12099:2;12084:18;;11758:350::o;12113:339::-;12315:2;12297:21;;;12354:2;12334:18;;;12327:30;-1:-1:-1;;;12388:2:1;12373:18;;12366:45;12443:2;12428:18;;12113:339::o;13222:356::-;13424:2;13406:21;;;13443:18;;;13436:30;13502:34;13497:2;13482:18;;13475:62;13569:2;13554:18;;13222:356::o;13943:168::-;14016:9;;;14047;;14064:15;;;14058:22;;14044:37;14034:71;;14085:18;;:::i;14116:217::-;14156:1;14182;14172:132;;14226:10;14221:3;14217:20;14214:1;14207:31;14261:4;14258:1;14251:15;14289:4;14286:1;14279:15;14172:132;-1:-1:-1;14318:9:1;;14116:217::o;17688:346::-;17890:2;17872:21;;;17929:2;17909:18;;;17902:30;-1:-1:-1;;;17963:2:1;17948:18;;17941:52;18025:2;18010:18;;17688:346::o;21028:135::-;21067:3;21088:17;;;21085:43;;21108:18;;:::i;:::-;-1:-1:-1;21155:1:1;21144:13;;21028:135::o;23055:401::-;23257:2;23239:21;;;23296:2;23276:18;;;23269:30;23335:34;23330:2;23315:18;;23308:62;-1:-1:-1;;;23401:2:1;23386:18;;23379:35;23446:3;23431:19;;23055:401::o;23461:399::-;23663:2;23645:21;;;23702:2;23682:18;;;23675:30;23741:34;23736:2;23721:18;;23714:62;-1:-1:-1;;;23807:2:1;23792:18;;23785:33;23850:3;23835:19;;23461:399::o;25843:212::-;25885:3;25923:5;25917:12;25967:6;25960:4;25953:5;25949:16;25944:3;25938:36;26029:1;25993:16;;26018:13;;;-1:-1:-1;25993:16:1;;25843:212;-1:-1:-1;25843:212:1:o;26060:595::-;26471:25;26466:3;26459:38;26441:3;26516:39;26551:2;26546:3;26542:12;26534:6;26516:39;:::i;:::-;-1:-1:-1;;;26571:2:1;26564:31;26611:38;26645:2;26641;26637:11;26629:6;26611:38;:::i;:::-;26604:45;26060:595;-1:-1:-1;;;;;26060:595:1:o;27814:127::-;27875:10;27870:3;27866:20;27863:1;27856:31;27906:4;27903:1;27896:15;27930:4;27927:1;27920:15;27946:136;27985:3;28013:5;28003:39;;28022:18;;:::i;:::-;-1:-1:-1;;;28058:18:1;;27946:136::o

Swarm Source

ipfs://138359922dceabe5dd9dd1110cc852884aa60666f863717570de2eb733165efc
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.