ETH Price: $3,247.42 (-2.64%)
 

Overview

Max Total Supply

100,000,000 GLDS

Holders

26

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
0.000000000027504388 GLDS

Value
$0.00
0xE30ce57D34e6A9CBD29ad4C120212B21f4139dB3
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
Glades

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2025-01-22
*/

// File: @openzeppelin/[email protected]/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/IERC20Metadata.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;


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

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

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

// File: @openzeppelin/[email protected]/utils/Context.sol


// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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;
    }
}

// File: @openzeppelin/[email protected]/interfaces/draft-IERC6093.sol


// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

// File: @openzeppelin/[email protected]/token/ERC20/ERC20.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;





/**
 * @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}.
 *
 * 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 ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => 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 returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual 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 returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual 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 `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` 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 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * 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 `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` 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.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` 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.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

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

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Burnable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.20;



/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys a `value` amount of tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 value) public virtual {
        _burn(_msgSender(), value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, deducting from
     * the caller's allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `value`.
     */
    function burnFrom(address account, uint256 value) public virtual {
        _spendAllowance(account, _msgSender(), value);
        _burn(account, value);
    }
}

// File: @openzeppelin/[email protected]/utils/Pausable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;


/**
 * @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 {
    bool private _paused;

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

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @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 {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

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

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Pausable.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Pausable.sol)

pragma solidity ^0.8.20;



/**
 * @dev ERC-20 token with pausable token transfers, minting and burning.
 *
 * Useful for scenarios such as preventing trades until the end of an evaluation
 * period, or having an emergency switch for freezing all token transfers in the
 * event of a large bug.
 *
 * IMPORTANT: This contract does not include public pause and unpause functions. In
 * addition to inheriting this contract, you must define both functions, invoking the
 * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate
 * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will
 * make the contract pause mechanism of the contract unreachable, and thus unusable.
 */
abstract contract ERC20Pausable is ERC20, Pausable {
    /**
     * @dev See {ERC20-_update}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _update(address from, address to, uint256 value) internal virtual override whenNotPaused {
        super._update(from, to, value);
    }
}

// File: @openzeppelin/[email protected]/access/IAccessControl.sol


// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @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.
     */
    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. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    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 `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

// File: @openzeppelin/[email protected]/utils/introspection/IERC165.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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);
}

// File: @openzeppelin/[email protected]/utils/introspection/ERC165.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 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);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: @openzeppelin/[email protected]/access/AccessControl.sol


// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;




/**
 * @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 account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    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 returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @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 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 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 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 `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @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 Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/IERC20Permit.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// File: @openzeppelin/[email protected]/utils/cryptography/ECDSA.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS
    }

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     */
    function tryRecover(
        bytes32 hash,
        bytes memory signature
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly ("memory-safe") {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        unchecked {
            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS, s);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature, bytes32(0));
        }

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}

// File: @openzeppelin/[email protected]/utils/Panic.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)

pragma solidity ^0.8.20;

/**
 * @dev Helper library for emitting standardized panic codes.
 *
 * ```solidity
 * contract Example {
 *      using Panic for uint256;
 *
 *      // Use any of the declared internal constants
 *      function foo() { Panic.GENERIC.panic(); }
 *
 *      // Alternatively
 *      function foo() { Panic.panic(Panic.GENERIC); }
 * }
 * ```
 *
 * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 *
 * _Available since v5.1._
 */
// slither-disable-next-line unused-state
library Panic {
    /// @dev generic / unspecified error
    uint256 internal constant GENERIC = 0x00;
    /// @dev used by the assert() builtin
    uint256 internal constant ASSERT = 0x01;
    /// @dev arithmetic underflow or overflow
    uint256 internal constant UNDER_OVERFLOW = 0x11;
    /// @dev division or modulo by zero
    uint256 internal constant DIVISION_BY_ZERO = 0x12;
    /// @dev enum conversion error
    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
    /// @dev invalid encoding in storage
    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
    /// @dev empty array pop
    uint256 internal constant EMPTY_ARRAY_POP = 0x31;
    /// @dev array out of bounds access
    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
    /// @dev resource error (too large allocation or too large array)
    uint256 internal constant RESOURCE_ERROR = 0x41;
    /// @dev calling invalid internal function
    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;

    /// @dev Reverts with a panic code. Recommended to use with
    /// the internal constants with predefined codes.
    function panic(uint256 code) internal pure {
        assembly ("memory-safe") {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}

// File: @openzeppelin/[email protected]/utils/math/SafeCast.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

// File: @openzeppelin/[email protected]/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;



/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * SafeCast.toUint(condition));
        }
    }

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

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(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 towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }

        // The following calculation ensures accurate ceiling division without overflow.
        // Since a is non-zero, (a - 1) / b will not overflow.
        // The largest possible result occurs when (a - 1) / b is type(uint256).max,
        // but the largest value we can obtain is type(uint256).max - 1, which happens
        // when a = type(uint256).max and b = 1.
        unchecked {
            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
        }
    }

    /**
     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     *
     * 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²⁵⁶ and mod 2²⁵⁶ - 1, then use
            // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2²⁵⁶ + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                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²⁵⁶. Also prevents denominator == 0.
            if (denominator <= prod1) {
                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_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.

            uint256 twos = denominator & (0 - denominator);
            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²⁵⁶ / 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²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
            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⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
            inverse *= 2 - denominator * inverse; // inverse mod 2³²
            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶

            // 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²⁵⁶. Since the preconditions guarantee that the outcome is
            // less than 2²⁵⁶, 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;
        }
    }

    /**
     * @dev 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) {
        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
    }

    /**
     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
     *
     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
     *
     * If the input value is not inversible, 0 is returned.
     *
     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
     */
    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
        unchecked {
            if (n == 0) return 0;

            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
            // Used to compute integers x and y such that: ax + ny = gcd(a, n).
            // When the gcd is 1, then the inverse of a modulo n exists and it's x.
            // ax + ny = 1
            // ax = 1 + (-y)n
            // ax ≡ 1 (mod n) # x is the inverse of a modulo n

            // If the remainder is 0 the gcd is n right away.
            uint256 remainder = a % n;
            uint256 gcd = n;

            // Therefore the initial coefficients are:
            // ax + ny = gcd(a, n) = n
            // 0a + 1n = n
            int256 x = 0;
            int256 y = 1;

            while (remainder != 0) {
                uint256 quotient = gcd / remainder;

                (gcd, remainder) = (
                    // The old remainder is the next gcd to try.
                    remainder,
                    // Compute the next remainder.
                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
                    // where gcd is at most n (capped to type(uint256).max)
                    gcd - remainder * quotient
                );

                (x, y) = (
                    // Increment the coefficient of a.
                    y,
                    // Decrement the coefficient of n.
                    // Can overflow, but the result is casted to uint256 so that the
                    // next value of y is "wrapped around" to a value between 0 and n - 1.
                    x - y * int256(quotient)
                );
            }

            if (gcd != 1) return 0; // No inverse exists.
            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
        }
    }

    /**
     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
     *
     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.
     *
     * NOTE: this function does NOT check that `p` is a prime greater than `2`.
     */
    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
        unchecked {
            return Math.modExp(a, p - 2, p);
        }
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
     *
     * Requirements:
     * - modulus can't be zero
     * - underlying staticcall to precompile must succeed
     *
     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
     * sure the chain you're using it on supports the precompiled contract for modular exponentiation
     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
     * interpreted as 0.
     */
    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
        (bool success, uint256 result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
     * to operate modulo 0 or if the underlying precompile reverted.
     *
     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
     * of a revert, but the result may be incorrectly interpreted as 0.
     */
    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
        if (m == 0) return (false, 0);
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            // | Offset    | Content    | Content (Hex)                                                      |
            // |-----------|------------|--------------------------------------------------------------------|
            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x60:0x7f | value of b | 0x<.............................................................b> |
            // | 0x80:0x9f | value of e | 0x<.............................................................e> |
            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
            mstore(ptr, 0x20)
            mstore(add(ptr, 0x20), 0x20)
            mstore(add(ptr, 0x40), 0x20)
            mstore(add(ptr, 0x60), b)
            mstore(add(ptr, 0x80), e)
            mstore(add(ptr, 0xa0), m)

            // Given the result < m, it's guaranteed to fit in 32 bytes,
            // so we can use the memory scratch space located at offset 0.
            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
            result := mload(0x00)
        }
    }

    /**
     * @dev Variant of {modExp} that supports inputs of arbitrary length.
     */
    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
        (bool success, bytes memory result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
     */
    function tryModExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bool success, bytes memory result) {
        if (_zeroBytes(m)) return (false, new bytes(0));

        uint256 mLen = m.length;

        // Encode call args in result and move the free memory pointer
        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);

        assembly ("memory-safe") {
            let dataPtr := add(result, 0x20)
            // Write result on top of args to avoid allocating extra memory.
            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
            // Overwrite the length.
            // result.length > returndatasize() is guaranteed because returndatasize() == m.length
            mstore(result, mLen)
            // Set the memory pointer after the returned data.
            mstore(0x40, add(dataPtr, mLen))
        }
    }

    /**
     * @dev Returns whether the provided byte array is zero.
     */
    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
        for (uint256 i = 0; i < byteArray.length; ++i) {
            if (byteArray[i] != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
     * using integer operations.
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        unchecked {
            // Take care of easy edge cases when a == 0 or a == 1
            if (a <= 1) {
                return a;
            }

            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
            // the current value as `ε_n = | x_n - sqrt(a) |`.
            //
            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
            // bigger than any uint256.
            //
            // By noticing that
            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
            // to the msb function.
            uint256 aa = a;
            uint256 xn = 1;

            if (aa >= (1 << 128)) {
                aa >>= 128;
                xn <<= 64;
            }
            if (aa >= (1 << 64)) {
                aa >>= 64;
                xn <<= 32;
            }
            if (aa >= (1 << 32)) {
                aa >>= 32;
                xn <<= 16;
            }
            if (aa >= (1 << 16)) {
                aa >>= 16;
                xn <<= 8;
            }
            if (aa >= (1 << 8)) {
                aa >>= 8;
                xn <<= 4;
            }
            if (aa >= (1 << 4)) {
                aa >>= 4;
                xn <<= 2;
            }
            if (aa >= (1 << 2)) {
                xn <<= 1;
            }

            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
            //
            // We can refine our estimation by noticing that the middle of that interval minimizes the error.
            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
            // This is going to be our x_0 (and ε_0)
            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)

            // From here, Newton's method give us:
            // x_{n+1} = (x_n + a / x_n) / 2
            //
            // One should note that:
            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
            //              = ((x_n² + a) / (2 * x_n))² - a
            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
            //              = (x_n² - a)² / (2 * x_n)²
            //              = ((x_n² - a) / (2 * x_n))²
            //              ≥ 0
            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
            //
            // This gives us the proof of quadratic convergence of the sequence:
            // ε_{n+1} = | x_{n+1} - sqrt(a) |
            //         = | (x_n + a / x_n) / 2 - sqrt(a) |
            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
            //         = | (x_n - sqrt(a))² / (2 * x_n) |
            //         = | ε_n² / (2 * x_n) |
            //         = ε_n² / | (2 * x_n) |
            //
            // For the first iteration, we have a special case where x_0 is known:
            // ε_1 = ε_0² / | (2 * x_0) |
            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
            //     ≤ 2**(e-3) / 3
            //     ≤ 2**(e-3-log2(3))
            //     ≤ 2**(e-4.5)
            //
            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
            // ε_{n+1} = ε_n² / | (2 * x_n) |
            //         ≤ (2**(e-k))² / (2 * 2**(e-1))
            //         ≤ 2**(2*e-2*k) / 2**e
            //         ≤ 2**(e-2*k)
            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72

            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
            // sqrt(a) or sqrt(a) + 1.
            return xn - SafeCast.toUint(xn > a / xn);
        }
    }

    /**
     * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 exp;
        unchecked {
            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
            value >>= exp;
            result += exp;

            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
            value >>= exp;
            result += exp;

            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
            value >>= exp;
            result += exp;

            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
            value >>= exp;
            result += exp;

            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
            value >>= exp;
            result += exp;

            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
            value >>= exp;
            result += exp;

            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
            value >>= exp;
            result += exp;

            result += SafeCast.toUint(value > 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * 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;
        uint256 isGt;
        unchecked {
            isGt = SafeCast.toUint(value > (1 << 128) - 1);
            value >>= isGt * 128;
            result += isGt * 16;

            isGt = SafeCast.toUint(value > (1 << 64) - 1);
            value >>= isGt * 64;
            result += isGt * 8;

            isGt = SafeCast.toUint(value > (1 << 32) - 1);
            value >>= isGt * 32;
            result += isGt * 4;

            isGt = SafeCast.toUint(value > (1 << 16) - 1);
            value >>= isGt * 16;
            result += isGt * 2;

            result += SafeCast.toUint(value > (1 << 8) - 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

// File: @openzeppelin/[email protected]/utils/math/SignedMath.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;


/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
        }
    }

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

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return ternary(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 {
            // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
            // taking advantage of the most significant (or "sign" bit) in two's complement representation.
            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
            // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
            int256 mask = n >> 255;

            // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
            return uint256((n + mask) ^ mask);
        }
    }
}

// File: @openzeppelin/[email protected]/utils/Strings.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/Strings.sol)

pragma solidity ^0.8.20;



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

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @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;
            assembly ("memory-safe") {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                assembly ("memory-safe") {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(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) {
        uint256 localValue = value;
        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] = HEX_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        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 Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
     * representation, according to EIP-55.
     */
    function toChecksumHexString(address addr) internal pure returns (string memory) {
        bytes memory buffer = bytes(toHexString(addr));

        // hash the hex part of buffer (skip length + 2 bytes, length 40)
        uint256 hashValue;
        assembly ("memory-safe") {
            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
        }

        for (uint256 i = 41; i > 1; --i) {
            // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
                // case shift by xoring with 0x20
                buffer[i] ^= 0x20;
            }
            hashValue >>= 4;
        }
        return string(buffer);
    }

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

// File: @openzeppelin/[email protected]/utils/cryptography/MessageHashUtils.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MessageHashUtils.sol)

pragma solidity ^0.8.20;


/**
 * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
 *
 * The library provides methods for generating a hash of a message that conforms to the
 * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
 * specifications.
 */
library MessageHashUtils {
    /**
     * @dev Returns the keccak256 digest of an ERC-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing a bytes32 `messageHash` with
     * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
     * keccak256, although any bytes32 value can be safely used because the final digest will
     * be re-hashed.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
        assembly ("memory-safe") {
            mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
        }
    }

    /**
     * @dev Returns the keccak256 digest of an ERC-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing an arbitrary `message` with
     * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
        return
            keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
    }

    /**
     * @dev Returns the keccak256 digest of an ERC-191 signed data with version
     * `0x00` (data with intended validator).
     *
     * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
     * `validator` address. Then hashing the result.
     *
     * See {ECDSA-recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(hex"19_00", validator, data));
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
     *
     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
     * `\x19\x01` and hashing the result. It corresponds to the hash signed by the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
     *
     * See {ECDSA-recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            mstore(ptr, hex"19_01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            digest := keccak256(ptr, 0x42)
        }
    }
}

// File: @openzeppelin/[email protected]/utils/StorageSlot.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC-1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {SlotDerivation}.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Int256Slot` with member `value` located at `slot`.
     */
    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns a `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }
}

// File: @openzeppelin/[email protected]/utils/ShortStrings.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.20;


// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |
// | length  | 0x                                                              BB |
type ShortString is bytes32;

/**
 * @dev This library provides functions to convert short memory strings
 * into a `ShortString` type that can be used as an immutable variable.
 *
 * Strings of arbitrary length can be optimized using this library if
 * they are short enough (up to 31 bytes) by packing them with their
 * length (1 byte) in a single EVM word (32 bytes). Additionally, a
 * fallback mechanism can be used for every other case.
 *
 * Usage example:
 *
 * ```solidity
 * contract Named {
 *     using ShortStrings for *;
 *
 *     ShortString private immutable _name;
 *     string private _nameFallback;
 *
 *     constructor(string memory contractName) {
 *         _name = contractName.toShortStringWithFallback(_nameFallback);
 *     }
 *
 *     function name() external view returns (string memory) {
 *         return _name.toStringWithFallback(_nameFallback);
 *     }
 * }
 * ```
 */
library ShortStrings {
    // Used as an identifier for strings longer than 31 bytes.
    bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;

    error StringTooLong(string str);
    error InvalidShortString();

    /**
     * @dev Encode a string of at most 31 chars into a `ShortString`.
     *
     * This will trigger a `StringTooLong` error is the input string is too long.
     */
    function toShortString(string memory str) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    /**
     * @dev Decode a `ShortString` back to a "normal" string.
     */
    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = byteLength(sstr);
        // using `new string(len)` would work locally but is not memory safe.
        string memory str = new string(32);
        assembly ("memory-safe") {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    /**
     * @dev Return the length of a `ShortString`.
     */
    function byteLength(ShortString sstr) internal pure returns (uint256) {
        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
        if (result > 31) {
            revert InvalidShortString();
        }
        return result;
    }

    /**
     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
     */
    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(FALLBACK_SENTINEL);
        }
    }

    /**
     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     */
    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return toString(value);
        } else {
            return store;
        }
    }

    /**
     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using
     * {setWithFallback}.
     *
     * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
     */
    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return byteLength(value);
        } else {
            return bytes(store).length;
        }
    }
}

// File: @openzeppelin/[email protected]/interfaces/IERC5267.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.20;

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

// File: @openzeppelin/[email protected]/utils/cryptography/EIP712.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.20;




/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
 * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
 * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
 * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
 * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the
 * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable
 */
abstract contract EIP712 is IERC5267 {
    using ShortStrings for *;

    bytes32 private constant TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    ShortString private immutable _name;
    ShortString private immutable _version;
    string private _nameFallback;
    string private _versionFallback;

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
            return _cachedDomainSeparator;
        } else {
            return _buildDomainSeparator();
        }
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev See {IERC-5267}.
     */
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _EIP712Name(),
            _EIP712Version(),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }

    /**
     * @dev The name parameter for the EIP712 domain.
     *
     * NOTE: By default this function reads _name which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _EIP712Name() internal view returns (string memory) {
        return _name.toStringWithFallback(_nameFallback);
    }

    /**
     * @dev The version parameter for the EIP712 domain.
     *
     * NOTE: By default this function reads _version which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _EIP712Version() internal view returns (string memory) {
        return _version.toStringWithFallback(_versionFallback);
    }
}

// File: @openzeppelin/[email protected]/utils/Nonces.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)
pragma solidity ^0.8.20;

/**
 * @dev Provides tracking nonces for addresses. Nonces will only increment.
 */
abstract contract Nonces {
    /**
     * @dev The nonce used for an `account` is not the expected current nonce.
     */
    error InvalidAccountNonce(address account, uint256 currentNonce);

    mapping(address account => uint256) private _nonces;

    /**
     * @dev Returns the next unused nonce for an address.
     */
    function nonces(address owner) public view virtual returns (uint256) {
        return _nonces[owner];
    }

    /**
     * @dev Consumes a nonce.
     *
     * Returns the current value and increments nonce.
     */
    function _useNonce(address owner) internal virtual returns (uint256) {
        // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be
        // decremented or reset. This guarantees that the nonce never overflows.
        unchecked {
            // It is important to do x++ and not ++x here.
            return _nonces[owner]++;
        }
    }

    /**
     * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.
     */
    function _useCheckedNonce(address owner, uint256 nonce) internal virtual {
        uint256 current = _useNonce(owner);
        if (nonce != current) {
            revert InvalidAccountNonce(owner, current);
        }
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Permit.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Permit.sol)

pragma solidity ^0.8.20;






/**
 * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
    bytes32 private constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    /**
     * @dev Permit deadline has expired.
     */
    error ERC2612ExpiredSignature(uint256 deadline);

    /**
     * @dev Mismatched signature.
     */
    error ERC2612InvalidSigner(address signer, address owner);

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC-20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @inheritdoc IERC20Permit
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        if (block.timestamp > deadline) {
            revert ERC2612ExpiredSignature(deadline);
        }

        bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        if (signer != owner) {
            revert ERC2612InvalidSigner(signer, owner);
        }

        _approve(owner, spender, value);
    }

    /**
     * @inheritdoc IERC20Permit
     */
    function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) {
        return super.nonces(owner);
    }

    /**
     * @inheritdoc IERC20Permit
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {
        return _domainSeparatorV4();
    }
}

// File: @openzeppelin/[email protected]/utils/structs/EnumerableSet.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }
}

// File: contracts/Blacklistable.sol

/**
 * Copyright (c) 2018-2020 CENTRE SECZ
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

pragma solidity 0.8.28;  


/**  
 * @title Blacklistable Token  
 * @dev Allows accounts to be blacklisted by a "blacklister" role  
 */  
abstract contract Blacklistable is Context {  
    mapping(address => bool) internal blacklisted;  

    event Blacklisted(address indexed _account);  
    event Unblacklisted(address indexed _account);  

    /**  
     * @dev Throws if argument account is blacklisted  
     * @param _account The address to check  
     */  
    modifier notBlacklisted(address _account) {  
        require(  
            !blacklisted[_account],  
            "Blacklistable: account is blacklisted"  
        );  
        _;  
    }  

    /**  
     * @dev Checks if account is blacklisted  
     * @param _account The address to check  
     */  
    function isBlacklisted(address _account) external view returns (bool) {  
        return blacklisted[_account];  
    }  

    /**  
     * @dev Adds account to blacklist  
     * @param _account The address to blacklist  
     */  
    function _blacklist(address _account) internal virtual {  
        blacklisted[_account] = true;  
        emit Blacklisted(_account);  
    }  

    /**  
     * @dev Removes account from blacklist  
     * @param _account The address to remove from the blacklist  
     */  
    function _unblacklist(address _account) internal virtual {  
        blacklisted[_account] = false;  
        emit Unblacklisted(_account);  
    }  
}  

// File: contracts/Glades.sol


pragma solidity ^0.8.28;








contract Glades is ERC20, ERC20Burnable, ERC20Pausable, AccessControl, ERC20Permit, Blacklistable {
    using EnumerableSet for EnumerableSet.AddressSet;

    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant BLACKLISTER_ROLE = keccak256("BLACKLISTER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant TAX_ROLE = keccak256("TAX_ROLE");

    address public taxReceiver;
    uint16 public buyTaxBps;
    uint16 public sellTaxBps;
    uint16 public transferTaxBps;
    uint16 public buyLimit;

    // Track which addresses do not incur tax
    mapping(address => bool) public excludedFromTax;

    // Track which pairs should be taxed (i.e., recognized as swap pairs)
    EnumerableSet.AddressSet private swapV2Pairs;

    event TaxReceiverSet(address indexed receiver);
    event TaxesSet(uint16 buyTaxBps, uint16 sellTaxBps, uint16 transferTaxBps);
    event ExcludedFromTax(address indexed target);
    event IncludedInTax(address indexed target);
    event NewTaxableSwapPair(address indexed pair);

    constructor() ERC20("Glades", "GLDS") ERC20Permit("Glades") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);
        _grantRole(BLACKLISTER_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
        _grantRole(TAX_ROLE, msg.sender);

	buyLimit = 2;

        // Mint initial supply to deployer
        _mint(msg.sender, 100000000 * 10 ** decimals());
    }

    function pause() public onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() public onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        _mint(to, amount);
    }

    function blacklist(address account) public onlyRole(BLACKLISTER_ROLE) {
        _blacklist(account);
    }

    function unblacklist(address account) public onlyRole(BLACKLISTER_ROLE) {
        _unblacklist(account);
    }

    // ------------------------------------------------------------------------
    // Override transfer(...) to apply buy/sell/transfer tax logic
    // ------------------------------------------------------------------------
    function transfer(address to, uint256 amount) public override returns (bool) {
        _taxedTransfer(msg.sender, to, amount);
        return true;
    }

    // ------------------------------------------------------------------------
    // Override transferFrom(...) to also apply buy/sell/transfer tax logic
    // ------------------------------------------------------------------------
    function transferFrom(address from, address to, uint256 amount) public override returns (bool) {
        // Standard ERC20 allowance check
        uint256 currentAllowance = allowance(from, msg.sender);
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        _approve(from, msg.sender, currentAllowance - amount);

        _taxedTransfer(from, to, amount);
        return true;
    }

    // ------------------------------------------------------------------------
    // Private function that unifies the logic for transfer and transferFrom
    // ------------------------------------------------------------------------
    function _taxedTransfer(address from, address to, uint256 amount) private {
        // If the recipient (or sender) is excluded from tax, skip any checks or taxes
        if (excludedFromTax[from] || excludedFromTax[to]) {
            _transfer(from, to, amount);
            return;
        }

        // Check if this is a sell (to a swap pair), apply sell tax
        if (swapV2Pairs.contains(to)) {
            if (sellTaxBps > 0) {
                _transferTaxed(from, to, amount, sellTaxBps);
            } else {
                _transfer(from, to, amount);
            }

        // Check if this is a buy (from a swap pair), apply buy limit + buy tax
        } else if (swapV2Pairs.contains(from)) {
            // Enforce X% limit of the total supply on each buy
            require(
                amount <= (totalSupply() * buyLimit) / 100,
                "GLDS: Buy exceeds buy limit % of total supply"
            );

            if (buyTaxBps > 0) {
                _transferTaxed(from, to, amount, buyTaxBps);
            } else {
                _transfer(from, to, amount);
            }

        // Otherwise, apply transfer tax if any
        } else if (transferTaxBps > 0) {
            _transferTaxed(from, to, amount, transferTaxBps);

        // If no condition matches, just do a normal transfer
        } else {
            _transfer(from, to, amount);
        }
    }

    // ------------------------------------------------------------------------
    // Internal function to handle the actual taxed transfer
    // ------------------------------------------------------------------------
    function _transferTaxed(
        address from,
        address to,
        uint256 amount,
        uint16 taxBps
    ) private {
        uint256 taxAmount = (amount * taxBps) / 10000;
        uint256 leftAmount = amount - taxAmount;

        require(taxReceiver != address(0), "GLDS: taxReceiver is the zero address");

        // First transfer the tax to the taxReceiver
        _transfer(from, taxReceiver, taxAmount);

        // Then transfer the remainder to the intended recipient
        _transfer(from, to, leftAmount);
    }

    // -----------------------------------------
    // Tax & Swap Pair Configuration
    // -----------------------------------------

    function setTaxReceiver(address receiver) external onlyRole(TAX_ROLE) {
        require(receiver != address(0), "GLDS: Cannot set tax receiver to the zero address!");
        taxReceiver = receiver;
        emit TaxReceiverSet(receiver);
    }

    function setTaxes(uint16 buyTax, uint16 sellTax, uint16 transferTax) external onlyRole(TAX_ROLE) {
        require(buyTax <= 2000, "GLDS: buy tax is too high!");
        require(sellTax <= 2000, "GLDS: sell tax is too high!");
        require(transferTax <= 2000, "GLDS: transfer tax is too high!");

        buyTaxBps = buyTax;
        sellTaxBps = sellTax;
        transferTaxBps = transferTax;

        emit TaxesSet(buyTax, sellTax, transferTax);
    }

    function excludeFromTax(address target) external onlyRole(TAX_ROLE) {
        excludedFromTax[target] = true;
        emit ExcludedFromTax(target);
    }

    function includeInTax(address target) external onlyRole(TAX_ROLE) {
        excludedFromTax[target] = false;
        emit IncludedInTax(target);
    }

    function addTaxableSwapPair(address pairAddress) external onlyRole(TAX_ROLE) {
        require(!swapV2Pairs.contains(pairAddress), "GLDS: SwapV2Pair already added");
        swapV2Pairs.add(pairAddress);
        emit NewTaxableSwapPair(pairAddress);
    }

    function isTaxablePair(address pair) public view returns (bool) {
        return swapV2Pairs.contains(pair);
    }

    function setBuyLimit(uint16 newBuyLimit) external onlyRole(TAX_ROLE) {
        require(newBuyLimit <= 100, "GLDS: Max buy limit is too high!");
	require(newBuyLimit > 0, "GLDS: Max buy limit is too low!");
	buyLimit = newBuyLimit;
    }

    // -----------------------------------------
    // Required overrides
    // -----------------------------------------

    // Make sure that pausable checks and blacklisting checks still apply
    function _update(address from, address to, uint256 value)
        internal
        override(ERC20, ERC20Pausable)
    {
        super._update(from, to, value);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"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":true,"internalType":"address","name":"_account","type":"address"}],"name":"Blacklisted","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"}],"name":"ExcludedFromTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"}],"name":"IncludedInTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"}],"name":"NewTaxableSwapPair","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":"receiver","type":"address"}],"name":"TaxReceiverSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"buyTaxBps","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"sellTaxBps","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"transferTaxBps","type":"uint16"}],"name":"TaxesSet","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":true,"internalType":"address","name":"_account","type":"address"}],"name":"Unblacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BLACKLISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TAX_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pairAddress","type":"address"}],"name":"addTaxableSwapPair","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":"value","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":[{"internalType":"address","name":"account","type":"address"}],"name":"blacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyLimit","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyTaxBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"excludeFromTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"excludedFromTax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"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":"target","type":"address"}],"name":"includeInTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"isTaxablePair","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","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":[],"name":"sellTaxBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"newBuyLimit","type":"uint16"}],"name":"setBuyLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setTaxReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"buyTax","type":"uint16"},{"internalType":"uint16","name":"sellTax","type":"uint16"},{"internalType":"uint16","name":"transferTax","type":"uint16"}],"name":"setTaxes","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":[],"name":"taxReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"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":[],"name":"transferTaxBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unblacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

610160604052348015610010575f5ffd5b506040518060400160405280600681526020017f476c616465730000000000000000000000000000000000000000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600681526020017f476c6164657300000000000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f474c44530000000000000000000000000000000000000000000000000000000081525081600390816100f99190610af1565b5080600490816101099190610af1565b5050505f60055f6101000a81548160ff02191690831515021790555061013960078361030260201b90919060201c565b610120818152505061015560088261030260201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a0818152505061019261034f60201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050506101e25f5f1b336103a960201b60201c565b506102137f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336103a960201b60201c565b506102447f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e9336103a960201b60201c565b506102757f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336103a960201b60201c565b506102a67f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac336103a960201b60201c565b506002600b601a6101000a81548161ffff021916908361ffff1602179055506102fd336102d761049f60201b60201c565b600a6102e39190610d28565b6305f5e1006102f29190610d72565b6104a760201b60201c565b61101d565b5f6020835110156103235761031c8361052c60201b60201c565b9050610349565b826103338361059160201b60201c565b5f0190816103419190610af1565b5060ff5f1b90505b92915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e05161010051463060405160200161038e959493929190610e19565b60405160208183030381529060405280519060200120905090565b5f6103ba838361059a60201b60201c565b61049557600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506104326105fe60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610499565b5f90505b92915050565b5f6012905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610517575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161050e9190610e6a565b60405180910390fd5b6105285f838361060560201b60201c565b5050565b5f5f829050601f8151111561057857826040517f305a27a900000000000000000000000000000000000000000000000000000000815260040161056f9190610ee9565b60405180910390fd5b80518161058490610f36565b5f1c175f1b915050919050565b5f819050919050565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b61061683838361061b60201b60201c565b505050565b61062961063f60201b60201c565b61063a83838361068660201b60201c565b505050565b61064d61089f60201b60201c565b15610684576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106d6578060025f8282546106ca9190610f9c565b925050819055506107a4565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561075f578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161075693929190610fcf565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036107eb578060025f8282540392505081905550610835565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516108929190611004565b60405180910390a3505050565b5f60055f9054906101000a900460ff16905090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061092f57607f821691505b602082108103610942576109416108eb565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026109a47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610969565b6109ae8683610969565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6109f26109ed6109e8846109c6565b6109cf565b6109c6565b9050919050565b5f819050919050565b610a0b836109d8565b610a1f610a17826109f9565b848454610975565b825550505050565b5f5f905090565b610a36610a27565b610a41818484610a02565b505050565b5b81811015610a6457610a595f82610a2e565b600181019050610a47565b5050565b601f821115610aa957610a7a81610948565b610a838461095a565b81016020851015610a92578190505b610aa6610a9e8561095a565b830182610a46565b50505b505050565b5f82821c905092915050565b5f610ac95f1984600802610aae565b1980831691505092915050565b5f610ae18383610aba565b9150826002028217905092915050565b610afa826108b4565b67ffffffffffffffff811115610b1357610b126108be565b5b610b1d8254610918565b610b28828285610a68565b5f60209050601f831160018114610b59575f8415610b47578287015190505b610b518582610ad6565b865550610bb8565b601f198416610b6786610948565b5f5b82811015610b8e57848901518255600182019150602085019450602081019050610b69565b86831015610bab5784890151610ba7601f891682610aba565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b6001851115610c4257808604811115610c1e57610c1d610bc0565b5b6001851615610c2d5780820291505b8081029050610c3b85610bed565b9450610c02565b94509492505050565b5f82610c5a5760019050610d15565b81610c67575f9050610d15565b8160018114610c7d5760028114610c8757610cb6565b6001915050610d15565b60ff841115610c9957610c98610bc0565b5b8360020a915084821115610cb057610caf610bc0565b5b50610d15565b5060208310610133831016604e8410600b8410161715610ceb5782820a905083811115610ce657610ce5610bc0565b5b610d15565b610cf88484846001610bf9565b92509050818404811115610d0f57610d0e610bc0565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610d32826109c6565b9150610d3d83610d1c565b9250610d6a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484610c4b565b905092915050565b5f610d7c826109c6565b9150610d87836109c6565b9250828202610d95816109c6565b91508282048414831517610dac57610dab610bc0565b5b5092915050565b5f819050919050565b610dc581610db3565b82525050565b610dd4816109c6565b82525050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610e0382610dda565b9050919050565b610e1381610df9565b82525050565b5f60a082019050610e2c5f830188610dbc565b610e396020830187610dbc565b610e466040830186610dbc565b610e536060830185610dcb565b610e606080830184610e0a565b9695505050505050565b5f602082019050610e7d5f830184610e0a565b92915050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610ebb826108b4565b610ec58185610e83565b9350610ed5818560208601610e93565b610ede81610ea1565b840191505092915050565b5f6020820190508181035f830152610f018184610eb1565b905092915050565b5f81519050919050565b5f819050602082019050919050565b5f610f2d8251610db3565b80915050919050565b5f610f4082610f09565b82610f4a84610f13565b9050610f5581610f22565b92506020821015610f9557610f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802610969565b831692505b5050919050565b5f610fa6826109c6565b9150610fb1836109c6565b9250828201905080821115610fc957610fc8610bc0565b5b92915050565b5f606082019050610fe25f830186610e0a565b610fef6020830185610dcb565b610ffc6040830184610dcb565b949350505050565b5f6020820190506110175f830184610dcb565b92915050565b60805160a05160c05160e051610100516101205161014051613e2261106e5f395f61211701525f6120dc01525f6126d001525f6126af01525f611ba901525f611bff01525f611c280152613e225ff3fe608060405234801561000f575f5ffd5b5060043610610288575f3560e01c80637ecebe001161015a578063cd8de42c116100cc578063e17c4c7411610085578063e17c4c74146107c6578063e63ab1e9146107e2578063e6ef73d614610800578063f515e6f21461081e578063f9f92be41461083c578063fe575a871461085857610288565b8063cd8de42c14610706578063cffd129c14610722578063d505accf14610740578063d53913931461075c578063d547741f1461077a578063dd62ed3e1461079657610288565b8063989763ef1161011e578063989763ef1461061c578063a217fddf1461064c578063a9059cbb1461066a578063b8a09b711461069a578063c473413a146106ca578063c4e48398146106e857610288565b80637ecebe00146105705780638456cb59146105a057806384b0196e146105aa57806391d14854146105ce57806395d89b41146105fe57610288565b806336568abe116101fe5780635c975abb116101b75780635c975abb146104b257806360d1259e146104d057806370a08231146104ec57806375e3661e1461051c5780637747b3321461053857806379cc67901461055457610288565b806336568abe1461041a5780633f4ba83a1461043657806340c10f191461044057806342966c681461045c57806344be2eae14610478578063589210d91461049457610288565b806323b872dd1161025057806323b872dd14610346578063248a9ca3146103765780632f2ff15d146103a6578063313ce567146103c257806332cde664146103e05780633644e515146103fc57610288565b806301ffc9a71461028c57806306fdde03146102bc57806308249db8146102da578063095ea7b3146102f857806318160ddd14610328575b5f5ffd5b6102a660048036038101906102a19190612eb8565b610888565b6040516102b39190612efd565b60405180910390f35b6102c4610901565b6040516102d19190612f86565b60405180910390f35b6102e2610991565b6040516102ef9190612fbe565b60405180910390f35b610312600480360381019061030d9190613064565b6109b5565b60405161031f9190612efd565b60405180910390f35b6103306109d7565b60405161033d91906130b1565b60405180910390f35b610360600480360381019061035b91906130ca565b6109e0565b60405161036d9190612efd565b60405180910390f35b610390600480360381019061038b9190613144565b610a5e565b60405161039d9190612fbe565b60405180910390f35b6103c060048036038101906103bb919061316f565b610a7b565b005b6103ca610a9d565b6040516103d791906131c8565b60405180910390f35b6103fa60048036038101906103f59190613218565b610aa5565b005b610404610c42565b6040516104119190612fbe565b60405180910390f35b610434600480360381019061042f919061316f565b610c50565b005b61043e610ccb565b005b61045a60048036038101906104559190613064565b610d00565b005b61047660048036038101906104719190613268565b610d39565b005b610492600480360381019061048d9190613293565b610d4d565b005b61049c610e27565b6040516104a991906132cd565b60405180910390f35b6104ba610e3b565b6040516104c79190612efd565b60405180910390f35b6104ea60048036038101906104e59190613293565b610e50565b005b61050660048036038101906105019190613293565b610f16565b60405161051391906130b1565b60405180910390f35b61053660048036038101906105319190613293565b610f5b565b005b610552600480360381019061054d91906132e6565b610f92565b005b61056e60048036038101906105699190613064565b61106b565b005b61058a60048036038101906105859190613293565b61108b565b60405161059791906130b1565b60405180910390f35b6105a861109c565b005b6105b26110d1565b6040516105c59796959493929190613411565b60405180910390f35b6105e860048036038101906105e3919061316f565b611176565b6040516105f59190612efd565b60405180910390f35b6106066111da565b6040516106139190612f86565b60405180910390f35b61063660048036038101906106319190613293565b61126a565b6040516106439190612efd565b60405180910390f35b610654611287565b6040516106619190612fbe565b60405180910390f35b610684600480360381019061067f9190613064565b61128d565b6040516106919190612efd565b60405180910390f35b6106b460048036038101906106af9190613293565b6112a3565b6040516106c19190612efd565b60405180910390f35b6106d26112bf565b6040516106df91906132cd565b60405180910390f35b6106f06112d3565b6040516106fd91906132cd565b60405180910390f35b610720600480360381019061071b9190613293565b6112e7565b005b61072a611406565b60405161073791906132cd565b60405180910390f35b61075a600480360381019061075591906134bd565b61141a565b005b61076461155f565b6040516107719190612fbe565b60405180910390f35b610794600480360381019061078f919061316f565b611583565b005b6107b060048036038101906107ab919061355a565b6115a5565b6040516107bd91906130b1565b60405180910390f35b6107e060048036038101906107db9190613293565b611627565b005b6107ea6116ec565b6040516107f79190612fbe565b60405180910390f35b610808611710565b6040516108159190613598565b60405180910390f35b610826611735565b6040516108339190612fbe565b60405180910390f35b61085660048036038101906108519190613293565b611759565b005b610872600480360381019061086d9190613293565b611790565b60405161087f9190612efd565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108fa57506108f9826117e2565b5b9050919050565b606060038054610910906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461093c906135de565b80156109875780601f1061095e57610100808354040283529160200191610987565b820191905f5260205f20905b81548152906001019060200180831161096a57829003601f168201915b5050505050905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac81565b5f5f6109bf61184b565b90506109cc818585611852565b600191505092915050565b5f600254905090565b5f5f6109ec85336115a5565b905082811015610a31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a289061367e565b60405180910390fd5b610a4785338584610a4291906136c9565b611852565b610a52858585611864565b60019150509392505050565b5f60065f8381526020019081526020015f20600101549050919050565b610a8482610a5e565b610a8d81611aa8565b610a978383611abc565b50505050565b5f6012905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610acf81611aa8565b6107d08461ffff161115610b18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0f90613746565b60405180910390fd5b6107d08361ffff161115610b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b58906137ae565b60405180910390fd5b6107d08261ffff161115610baa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba190613816565b60405180910390fd5b83600b60146101000a81548161ffff021916908361ffff16021790555082600b60166101000a81548161ffff021916908361ffff16021790555081600b60186101000a81548161ffff021916908361ffff1602179055507f540dec552b2a7a44d3d6174e189be8d0b3e89bc5c82bc74c93a3b251afd123db848484604051610c3493929190613834565b60405180910390a150505050565b5f610c4b611ba6565b905090565b610c5861184b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610cbc576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cc68282611c5c565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610cf581611aa8565b610cfd611d46565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610d2a81611aa8565b610d348383611da7565b505050565b610d4a610d4461184b565b82611e26565b50565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610d7781611aa8565b610d8b82600d611ea590919063ffffffff16565b15610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc2906138b3565b60405180910390fd5b610ddf82600d611ed290919063ffffffff16565b508173ffffffffffffffffffffffffffffffffffffffff167f0847e23332122e80466494f0dcd8617569de17c0a7abb702e7b77c20e4a68fbd60405160405180910390a25050565b600b601a9054906101000a900461ffff1681565b5f60055f9054906101000a900460ff16905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610e7a81611aa8565b6001600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f80da454365b13711a276446e1f98b60c9e938b703654280adf3b288a15cc40a660405160405180910390a25050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e9610f8581611aa8565b610f8e82611eff565b5050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610fbc81611aa8565b60648261ffff161115611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ffb9061391b565b60405180910390fd5b5f8261ffff161161104a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104190613983565b60405180910390fd5b81600b601a6101000a81548161ffff021916908361ffff1602179055505050565b61107d8261107761184b565b83611f99565b6110878282611e26565b5050565b5f6110958261202b565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6110c681611aa8565b6110ce612071565b50565b5f6060805f5f5f60606110e26120d3565b6110ea61210e565b46305f5f1b5f67ffffffffffffffff811115611109576111086139a1565b5b6040519080825280602002602001820160405280156111375781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6060600480546111e9906135de565b80601f0160208091040260200160405190810160405280929190818152602001828054611215906135de565b80156112605780601f1061123757610100808354040283529160200191611260565b820191905f5260205f20905b81548152906001019060200180831161124357829003601f168201915b5050505050905090565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f5f1b81565b5f611299338484611864565b6001905092915050565b5f6112b882600d611ea590919063ffffffff16565b9050919050565b600b60149054906101000a900461ffff1681565b600b60189054906101000a900461ffff1681565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61131181611aa8565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361137f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137690613a3e565b60405180910390fd5b81600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167fb637765305c2a6e716ace8b4c731e205863b495f7cc0c7810a3af93dd2808a3060405160405180910390a25050565b600b60169054906101000a900461ffff1681565b8342111561145f57836040517f6279130200000000000000000000000000000000000000000000000000000000815260040161145691906130b1565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861148d8c612149565b896040516020016114a396959493929190613a5c565b6040516020818303038152906040528051906020012090505f6114c58261219c565b90505f6114d4828787876121b5565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461154857808a6040517f4b800e4600000000000000000000000000000000000000000000000000000000815260040161153f929190613abb565b60405180910390fd5b6115538a8a8a611852565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61158c82610a5e565b61159581611aa8565b61159f8383611c5c565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61165181611aa8565b5f600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167fac77091f326d74b3968d96338bee7ba39f7eaa8107f38905a3589d4f0e735bf560405160405180910390a25050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e981565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e961178381611aa8565b61178c826121e3565b5050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b61185f838383600161227e565b505050565b600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16806118ff5750600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b156119145761190f83838361244d565b611aa3565b61192882600d611ea590919063ffffffff16565b1561197b575f600b60169054906101000a900461ffff1661ffff16111561196a57611965838383600b60169054906101000a900461ffff1661253d565b611976565b61197583838361244d565b5b611aa2565b61198f83600d611ea590919063ffffffff16565b15611a57576064600b601a9054906101000a900461ffff1661ffff166119b36109d7565b6119bd9190613ae2565b6119c79190613b50565b811115611a09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0090613bf0565b60405180910390fd5b5f600b60149054906101000a900461ffff1661ffff161115611a4657611a41838383600b60149054906101000a900461ffff1661253d565b611a52565b611a5183838361244d565b5b611aa1565b5f600b60189054906101000a900461ffff1661ffff161115611a9457611a8f838383600b60189054906101000a900461ffff1661253d565b611aa0565b611a9f83838361244d565b5b5b5b5b505050565b611ab981611ab461184b565b61263a565b50565b5f611ac78383611176565b611b9c57600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611b3961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611ba0565b5f90505b92915050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611c2157507f000000000000000000000000000000000000000000000000000000000000000046145b15611c4e577f00000000000000000000000000000000000000000000000000000000000000009050611c59565b611c5661268b565b90505b90565b5f611c678383611176565b15611d3c575f60065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611cd961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611d40565b5f90505b92915050565b611d4e612720565b5f60055f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611d9061184b565b604051611d9d9190613598565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e17575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611e0e9190613598565b60405180910390fd5b611e225f8383612760565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e96575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611e8d9190613598565b60405180910390fd5b611ea1825f83612760565b5050565b5f611eca835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612770565b905092915050565b5f611ef7835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612790565b905092915050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f7534c63860313c46c473e4e98328f37017e9674e2162faf1a3ad7a96236c3b7b60405160405180910390a250565b5f611fa484846115a5565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146120255781811015612016578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161200d93929190613c0e565b60405180910390fd5b61202484848484035f61227e565b5b50505050565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6120796127f7565b600160055f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586120bc61184b565b6040516120c99190613598565b60405180910390a1565b606061210960077f000000000000000000000000000000000000000000000000000000000000000061283890919063ffffffff16565b905090565b606061214460087f000000000000000000000000000000000000000000000000000000000000000061283890919063ffffffff16565b905090565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f6121ae6121a8611ba6565b836128e5565b9050919050565b5f5f5f5f6121c588888888612925565b9250925092506121d58282612a0c565b829350505050949350505050565b6001600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85560405160405180910390a250565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122ee575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122e59190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361235e575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016123559190613598565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612447578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161243e91906130b1565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124bd575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016124b49190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361252d575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016125249190613598565b60405180910390fd5b612538838383612760565b505050565b5f6127108261ffff16846125519190613ae2565b61255b9190613b50565b90505f818461256a91906136c9565b90505f73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036125fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f290613cb3565b60405180910390fd5b61262786600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168461244d565b61263286868361244d565b505050505050565b6126448282611176565b6126875780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161267e929190613cd1565b60405180910390fd5b5050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001612705959493929190613cf8565b60405160208183030381529060405280519060200120905090565b612728610e3b565b61275e576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61276b838383612b6e565b505050565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f61279b8383612770565b6127ed57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f2081905550600190506127f1565b5f90505b92915050565b6127ff610e3b565b15612836576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b606060ff5f1b83146128545761284d83612b86565b90506128df565b818054612860906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461288c906135de565b80156128d75780601f106128ae576101008083540402835291602001916128d7565b820191905f5260205f20905b8154815290600101906020018083116128ba57829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f5f5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612961575f600385925092509250612a02565b5f6001888888886040515f81526020016040526040516129849493929190613d49565b6020604051602081039080840390855afa1580156129a4573d5f5f3e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129f5575f60015f5f1b93509350935050612a02565b805f5f5f1b935093509350505b9450945094915050565b5f6003811115612a1f57612a1e613d8c565b5b826003811115612a3257612a31613d8c565b5b0315612b6a5760016003811115612a4c57612a4b613d8c565b5b826003811115612a5f57612a5e613d8c565b5b03612a96576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612aaa57612aa9613d8c565b5b826003811115612abd57612abc613d8c565b5b03612b0157805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612af891906130b1565b60405180910390fd5b600380811115612b1457612b13613d8c565b5b826003811115612b2757612b26613d8c565b5b03612b6957806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612b609190612fbe565b60405180910390fd5b5b5050565b612b766127f7565b612b81838383612bf8565b505050565b60605f612b9283612e11565b90505f602067ffffffffffffffff811115612bb057612baf6139a1565b5b6040519080825280601f01601f191660200182016040528015612be25781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612c48578060025f828254612c3c9190613db9565b92505081905550612d16565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612cd1578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612cc893929190613c0e565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d5d578060025f8282540392505081905550612da7565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612e0491906130b1565b60405180910390a3505050565b5f5f60ff835f1c169050601f811115612e56576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612e9781612e63565b8114612ea1575f5ffd5b50565b5f81359050612eb281612e8e565b92915050565b5f60208284031215612ecd57612ecc612e5f565b5b5f612eda84828501612ea4565b91505092915050565b5f8115159050919050565b612ef781612ee3565b82525050565b5f602082019050612f105f830184612eee565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612f5882612f16565b612f628185612f20565b9350612f72818560208601612f30565b612f7b81612f3e565b840191505092915050565b5f6020820190508181035f830152612f9e8184612f4e565b905092915050565b5f819050919050565b612fb881612fa6565b82525050565b5f602082019050612fd15f830184612faf565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61300082612fd7565b9050919050565b61301081612ff6565b811461301a575f5ffd5b50565b5f8135905061302b81613007565b92915050565b5f819050919050565b61304381613031565b811461304d575f5ffd5b50565b5f8135905061305e8161303a565b92915050565b5f5f6040838503121561307a57613079612e5f565b5b5f6130878582860161301d565b925050602061309885828601613050565b9150509250929050565b6130ab81613031565b82525050565b5f6020820190506130c45f8301846130a2565b92915050565b5f5f5f606084860312156130e1576130e0612e5f565b5b5f6130ee8682870161301d565b93505060206130ff8682870161301d565b925050604061311086828701613050565b9150509250925092565b61312381612fa6565b811461312d575f5ffd5b50565b5f8135905061313e8161311a565b92915050565b5f6020828403121561315957613158612e5f565b5b5f61316684828501613130565b91505092915050565b5f5f6040838503121561318557613184612e5f565b5b5f61319285828601613130565b92505060206131a38582860161301d565b9150509250929050565b5f60ff82169050919050565b6131c2816131ad565b82525050565b5f6020820190506131db5f8301846131b9565b92915050565b5f61ffff82169050919050565b6131f7816131e1565b8114613201575f5ffd5b50565b5f81359050613212816131ee565b92915050565b5f5f5f6060848603121561322f5761322e612e5f565b5b5f61323c86828701613204565b935050602061324d86828701613204565b925050604061325e86828701613204565b9150509250925092565b5f6020828403121561327d5761327c612e5f565b5b5f61328a84828501613050565b91505092915050565b5f602082840312156132a8576132a7612e5f565b5b5f6132b58482850161301d565b91505092915050565b6132c7816131e1565b82525050565b5f6020820190506132e05f8301846132be565b92915050565b5f602082840312156132fb576132fa612e5f565b5b5f61330884828501613204565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61334581613311565b82525050565b61335481612ff6565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61338c81613031565b82525050565b5f61339d8383613383565b60208301905092915050565b5f602082019050919050565b5f6133bf8261335a565b6133c98185613364565b93506133d483613374565b805f5b838110156134045781516133eb8882613392565b97506133f6836133a9565b9250506001810190506133d7565b5085935050505092915050565b5f60e0820190506134245f83018a61333c565b81810360208301526134368189612f4e565b9050818103604083015261344a8188612f4e565b905061345960608301876130a2565b613466608083018661334b565b61347360a0830185612faf565b81810360c083015261348581846133b5565b905098975050505050505050565b61349c816131ad565b81146134a6575f5ffd5b50565b5f813590506134b781613493565b92915050565b5f5f5f5f5f5f5f60e0888a0312156134d8576134d7612e5f565b5b5f6134e58a828b0161301d565b97505060206134f68a828b0161301d565b96505060406135078a828b01613050565b95505060606135188a828b01613050565b94505060806135298a828b016134a9565b93505060a061353a8a828b01613130565b92505060c061354b8a828b01613130565b91505092959891949750929550565b5f5f604083850312156135705761356f612e5f565b5b5f61357d8582860161301d565b925050602061358e8582860161301d565b9150509250929050565b5f6020820190506135ab5f83018461334b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806135f557607f821691505b602082108103613608576136076135b1565b5b50919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320615f8201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b5f613668602883612f20565b91506136738261360e565b604082019050919050565b5f6020820190508181035f8301526136958161365c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6136d382613031565b91506136de83613031565b92508282039050818111156136f6576136f561369c565b5b92915050565b7f474c44533a206275792074617820697320746f6f2068696768210000000000005f82015250565b5f613730601a83612f20565b915061373b826136fc565b602082019050919050565b5f6020820190508181035f83015261375d81613724565b9050919050565b7f474c44533a2073656c6c2074617820697320746f6f20686967682100000000005f82015250565b5f613798601b83612f20565b91506137a382613764565b602082019050919050565b5f6020820190508181035f8301526137c58161378c565b9050919050565b7f474c44533a207472616e736665722074617820697320746f6f206869676821005f82015250565b5f613800601f83612f20565b915061380b826137cc565b602082019050919050565b5f6020820190508181035f83015261382d816137f4565b9050919050565b5f6060820190506138475f8301866132be565b61385460208301856132be565b61386160408301846132be565b949350505050565b7f474c44533a205377617056325061697220616c726561647920616464656400005f82015250565b5f61389d601e83612f20565b91506138a882613869565b602082019050919050565b5f6020820190508181035f8301526138ca81613891565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f2068696768215f82015250565b5f613905602083612f20565b9150613910826138d1565b602082019050919050565b5f6020820190508181035f830152613932816138f9565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f206c6f7721005f82015250565b5f61396d601f83612f20565b915061397882613939565b602082019050919050565b5f6020820190508181035f83015261399a81613961565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f474c44533a2043616e6e6f74207365742074617820726563656976657220746f5f8201527f20746865207a65726f2061646472657373210000000000000000000000000000602082015250565b5f613a28603283612f20565b9150613a33826139ce565b604082019050919050565b5f6020820190508181035f830152613a5581613a1c565b9050919050565b5f60c082019050613a6f5f830189612faf565b613a7c602083018861334b565b613a89604083018761334b565b613a9660608301866130a2565b613aa360808301856130a2565b613ab060a08301846130a2565b979650505050505050565b5f604082019050613ace5f83018561334b565b613adb602083018461334b565b9392505050565b5f613aec82613031565b9150613af783613031565b9250828202613b0581613031565b91508282048414831517613b1c57613b1b61369c565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613b5a82613031565b9150613b6583613031565b925082613b7557613b74613b23565b5b828204905092915050565b7f474c44533a20427579206578636565647320627579206c696d69742025206f665f8201527f20746f74616c20737570706c7900000000000000000000000000000000000000602082015250565b5f613bda602d83612f20565b9150613be582613b80565b604082019050919050565b5f6020820190508181035f830152613c0781613bce565b9050919050565b5f606082019050613c215f83018661334b565b613c2e60208301856130a2565b613c3b60408301846130a2565b949350505050565b7f474c44533a20746178526563656976657220697320746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f613c9d602583612f20565b9150613ca882613c43565b604082019050919050565b5f6020820190508181035f830152613cca81613c91565b9050919050565b5f604082019050613ce45f83018561334b565b613cf16020830184612faf565b9392505050565b5f60a082019050613d0b5f830188612faf565b613d186020830187612faf565b613d256040830186612faf565b613d3260608301856130a2565b613d3f608083018461334b565b9695505050505050565b5f608082019050613d5c5f830187612faf565b613d6960208301866131b9565b613d766040830185612faf565b613d836060830184612faf565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f613dc382613031565b9150613dce83613031565b9250828201905080821115613de657613de561369c565b5b9291505056fea2646970667358221220d7ae364ebf38f1292ad96706abfb172fe0c3b90d5b165210e3b69f8aacc4dccd64736f6c634300081c0033

Deployed Bytecode

0x608060405234801561000f575f5ffd5b5060043610610288575f3560e01c80637ecebe001161015a578063cd8de42c116100cc578063e17c4c7411610085578063e17c4c74146107c6578063e63ab1e9146107e2578063e6ef73d614610800578063f515e6f21461081e578063f9f92be41461083c578063fe575a871461085857610288565b8063cd8de42c14610706578063cffd129c14610722578063d505accf14610740578063d53913931461075c578063d547741f1461077a578063dd62ed3e1461079657610288565b8063989763ef1161011e578063989763ef1461061c578063a217fddf1461064c578063a9059cbb1461066a578063b8a09b711461069a578063c473413a146106ca578063c4e48398146106e857610288565b80637ecebe00146105705780638456cb59146105a057806384b0196e146105aa57806391d14854146105ce57806395d89b41146105fe57610288565b806336568abe116101fe5780635c975abb116101b75780635c975abb146104b257806360d1259e146104d057806370a08231146104ec57806375e3661e1461051c5780637747b3321461053857806379cc67901461055457610288565b806336568abe1461041a5780633f4ba83a1461043657806340c10f191461044057806342966c681461045c57806344be2eae14610478578063589210d91461049457610288565b806323b872dd1161025057806323b872dd14610346578063248a9ca3146103765780632f2ff15d146103a6578063313ce567146103c257806332cde664146103e05780633644e515146103fc57610288565b806301ffc9a71461028c57806306fdde03146102bc57806308249db8146102da578063095ea7b3146102f857806318160ddd14610328575b5f5ffd5b6102a660048036038101906102a19190612eb8565b610888565b6040516102b39190612efd565b60405180910390f35b6102c4610901565b6040516102d19190612f86565b60405180910390f35b6102e2610991565b6040516102ef9190612fbe565b60405180910390f35b610312600480360381019061030d9190613064565b6109b5565b60405161031f9190612efd565b60405180910390f35b6103306109d7565b60405161033d91906130b1565b60405180910390f35b610360600480360381019061035b91906130ca565b6109e0565b60405161036d9190612efd565b60405180910390f35b610390600480360381019061038b9190613144565b610a5e565b60405161039d9190612fbe565b60405180910390f35b6103c060048036038101906103bb919061316f565b610a7b565b005b6103ca610a9d565b6040516103d791906131c8565b60405180910390f35b6103fa60048036038101906103f59190613218565b610aa5565b005b610404610c42565b6040516104119190612fbe565b60405180910390f35b610434600480360381019061042f919061316f565b610c50565b005b61043e610ccb565b005b61045a60048036038101906104559190613064565b610d00565b005b61047660048036038101906104719190613268565b610d39565b005b610492600480360381019061048d9190613293565b610d4d565b005b61049c610e27565b6040516104a991906132cd565b60405180910390f35b6104ba610e3b565b6040516104c79190612efd565b60405180910390f35b6104ea60048036038101906104e59190613293565b610e50565b005b61050660048036038101906105019190613293565b610f16565b60405161051391906130b1565b60405180910390f35b61053660048036038101906105319190613293565b610f5b565b005b610552600480360381019061054d91906132e6565b610f92565b005b61056e60048036038101906105699190613064565b61106b565b005b61058a60048036038101906105859190613293565b61108b565b60405161059791906130b1565b60405180910390f35b6105a861109c565b005b6105b26110d1565b6040516105c59796959493929190613411565b60405180910390f35b6105e860048036038101906105e3919061316f565b611176565b6040516105f59190612efd565b60405180910390f35b6106066111da565b6040516106139190612f86565b60405180910390f35b61063660048036038101906106319190613293565b61126a565b6040516106439190612efd565b60405180910390f35b610654611287565b6040516106619190612fbe565b60405180910390f35b610684600480360381019061067f9190613064565b61128d565b6040516106919190612efd565b60405180910390f35b6106b460048036038101906106af9190613293565b6112a3565b6040516106c19190612efd565b60405180910390f35b6106d26112bf565b6040516106df91906132cd565b60405180910390f35b6106f06112d3565b6040516106fd91906132cd565b60405180910390f35b610720600480360381019061071b9190613293565b6112e7565b005b61072a611406565b60405161073791906132cd565b60405180910390f35b61075a600480360381019061075591906134bd565b61141a565b005b61076461155f565b6040516107719190612fbe565b60405180910390f35b610794600480360381019061078f919061316f565b611583565b005b6107b060048036038101906107ab919061355a565b6115a5565b6040516107bd91906130b1565b60405180910390f35b6107e060048036038101906107db9190613293565b611627565b005b6107ea6116ec565b6040516107f79190612fbe565b60405180910390f35b610808611710565b6040516108159190613598565b60405180910390f35b610826611735565b6040516108339190612fbe565b60405180910390f35b61085660048036038101906108519190613293565b611759565b005b610872600480360381019061086d9190613293565b611790565b60405161087f9190612efd565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108fa57506108f9826117e2565b5b9050919050565b606060038054610910906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461093c906135de565b80156109875780601f1061095e57610100808354040283529160200191610987565b820191905f5260205f20905b81548152906001019060200180831161096a57829003601f168201915b5050505050905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac81565b5f5f6109bf61184b565b90506109cc818585611852565b600191505092915050565b5f600254905090565b5f5f6109ec85336115a5565b905082811015610a31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a289061367e565b60405180910390fd5b610a4785338584610a4291906136c9565b611852565b610a52858585611864565b60019150509392505050565b5f60065f8381526020019081526020015f20600101549050919050565b610a8482610a5e565b610a8d81611aa8565b610a978383611abc565b50505050565b5f6012905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610acf81611aa8565b6107d08461ffff161115610b18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0f90613746565b60405180910390fd5b6107d08361ffff161115610b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b58906137ae565b60405180910390fd5b6107d08261ffff161115610baa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba190613816565b60405180910390fd5b83600b60146101000a81548161ffff021916908361ffff16021790555082600b60166101000a81548161ffff021916908361ffff16021790555081600b60186101000a81548161ffff021916908361ffff1602179055507f540dec552b2a7a44d3d6174e189be8d0b3e89bc5c82bc74c93a3b251afd123db848484604051610c3493929190613834565b60405180910390a150505050565b5f610c4b611ba6565b905090565b610c5861184b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610cbc576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cc68282611c5c565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610cf581611aa8565b610cfd611d46565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610d2a81611aa8565b610d348383611da7565b505050565b610d4a610d4461184b565b82611e26565b50565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610d7781611aa8565b610d8b82600d611ea590919063ffffffff16565b15610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc2906138b3565b60405180910390fd5b610ddf82600d611ed290919063ffffffff16565b508173ffffffffffffffffffffffffffffffffffffffff167f0847e23332122e80466494f0dcd8617569de17c0a7abb702e7b77c20e4a68fbd60405160405180910390a25050565b600b601a9054906101000a900461ffff1681565b5f60055f9054906101000a900460ff16905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610e7a81611aa8565b6001600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f80da454365b13711a276446e1f98b60c9e938b703654280adf3b288a15cc40a660405160405180910390a25050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e9610f8581611aa8565b610f8e82611eff565b5050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610fbc81611aa8565b60648261ffff161115611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ffb9061391b565b60405180910390fd5b5f8261ffff161161104a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104190613983565b60405180910390fd5b81600b601a6101000a81548161ffff021916908361ffff1602179055505050565b61107d8261107761184b565b83611f99565b6110878282611e26565b5050565b5f6110958261202b565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6110c681611aa8565b6110ce612071565b50565b5f6060805f5f5f60606110e26120d3565b6110ea61210e565b46305f5f1b5f67ffffffffffffffff811115611109576111086139a1565b5b6040519080825280602002602001820160405280156111375781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6060600480546111e9906135de565b80601f0160208091040260200160405190810160405280929190818152602001828054611215906135de565b80156112605780601f1061123757610100808354040283529160200191611260565b820191905f5260205f20905b81548152906001019060200180831161124357829003601f168201915b5050505050905090565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f5f1b81565b5f611299338484611864565b6001905092915050565b5f6112b882600d611ea590919063ffffffff16565b9050919050565b600b60149054906101000a900461ffff1681565b600b60189054906101000a900461ffff1681565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61131181611aa8565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361137f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137690613a3e565b60405180910390fd5b81600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167fb637765305c2a6e716ace8b4c731e205863b495f7cc0c7810a3af93dd2808a3060405160405180910390a25050565b600b60169054906101000a900461ffff1681565b8342111561145f57836040517f6279130200000000000000000000000000000000000000000000000000000000815260040161145691906130b1565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861148d8c612149565b896040516020016114a396959493929190613a5c565b6040516020818303038152906040528051906020012090505f6114c58261219c565b90505f6114d4828787876121b5565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461154857808a6040517f4b800e4600000000000000000000000000000000000000000000000000000000815260040161153f929190613abb565b60405180910390fd5b6115538a8a8a611852565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61158c82610a5e565b61159581611aa8565b61159f8383611c5c565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61165181611aa8565b5f600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167fac77091f326d74b3968d96338bee7ba39f7eaa8107f38905a3589d4f0e735bf560405160405180910390a25050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e981565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e961178381611aa8565b61178c826121e3565b5050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b61185f838383600161227e565b505050565b600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16806118ff5750600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b156119145761190f83838361244d565b611aa3565b61192882600d611ea590919063ffffffff16565b1561197b575f600b60169054906101000a900461ffff1661ffff16111561196a57611965838383600b60169054906101000a900461ffff1661253d565b611976565b61197583838361244d565b5b611aa2565b61198f83600d611ea590919063ffffffff16565b15611a57576064600b601a9054906101000a900461ffff1661ffff166119b36109d7565b6119bd9190613ae2565b6119c79190613b50565b811115611a09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0090613bf0565b60405180910390fd5b5f600b60149054906101000a900461ffff1661ffff161115611a4657611a41838383600b60149054906101000a900461ffff1661253d565b611a52565b611a5183838361244d565b5b611aa1565b5f600b60189054906101000a900461ffff1661ffff161115611a9457611a8f838383600b60189054906101000a900461ffff1661253d565b611aa0565b611a9f83838361244d565b5b5b5b5b505050565b611ab981611ab461184b565b61263a565b50565b5f611ac78383611176565b611b9c57600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611b3961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611ba0565b5f90505b92915050565b5f7f0000000000000000000000003d5dc167c4657565e8045c22040d242b25b9b1a673ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611c2157507f000000000000000000000000000000000000000000000000000000000000000146145b15611c4e577ff65d8fc27a5476ab4c899088df99f4835cd92c88d0523a84096ca599b787ed319050611c59565b611c5661268b565b90505b90565b5f611c678383611176565b15611d3c575f60065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611cd961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611d40565b5f90505b92915050565b611d4e612720565b5f60055f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611d9061184b565b604051611d9d9190613598565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e17575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611e0e9190613598565b60405180910390fd5b611e225f8383612760565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e96575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611e8d9190613598565b60405180910390fd5b611ea1825f83612760565b5050565b5f611eca835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612770565b905092915050565b5f611ef7835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612790565b905092915050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f7534c63860313c46c473e4e98328f37017e9674e2162faf1a3ad7a96236c3b7b60405160405180910390a250565b5f611fa484846115a5565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146120255781811015612016578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161200d93929190613c0e565b60405180910390fd5b61202484848484035f61227e565b5b50505050565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6120796127f7565b600160055f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586120bc61184b565b6040516120c99190613598565b60405180910390a1565b606061210960077f476c61646573000000000000000000000000000000000000000000000000000661283890919063ffffffff16565b905090565b606061214460087f310000000000000000000000000000000000000000000000000000000000000161283890919063ffffffff16565b905090565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f6121ae6121a8611ba6565b836128e5565b9050919050565b5f5f5f5f6121c588888888612925565b9250925092506121d58282612a0c565b829350505050949350505050565b6001600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85560405160405180910390a250565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122ee575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122e59190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361235e575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016123559190613598565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612447578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161243e91906130b1565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124bd575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016124b49190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361252d575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016125249190613598565b60405180910390fd5b612538838383612760565b505050565b5f6127108261ffff16846125519190613ae2565b61255b9190613b50565b90505f818461256a91906136c9565b90505f73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036125fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f290613cb3565b60405180910390fd5b61262786600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168461244d565b61263286868361244d565b505050505050565b6126448282611176565b6126875780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161267e929190613cd1565b60405180910390fd5b5050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f4ef23e2235d6064549416ca0a4fdb6b85e980452d2c17f1de3f0efd649d1b60c7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001612705959493929190613cf8565b60405160208183030381529060405280519060200120905090565b612728610e3b565b61275e576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61276b838383612b6e565b505050565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f61279b8383612770565b6127ed57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f2081905550600190506127f1565b5f90505b92915050565b6127ff610e3b565b15612836576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b606060ff5f1b83146128545761284d83612b86565b90506128df565b818054612860906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461288c906135de565b80156128d75780601f106128ae576101008083540402835291602001916128d7565b820191905f5260205f20905b8154815290600101906020018083116128ba57829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f5f5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612961575f600385925092509250612a02565b5f6001888888886040515f81526020016040526040516129849493929190613d49565b6020604051602081039080840390855afa1580156129a4573d5f5f3e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129f5575f60015f5f1b93509350935050612a02565b805f5f5f1b935093509350505b9450945094915050565b5f6003811115612a1f57612a1e613d8c565b5b826003811115612a3257612a31613d8c565b5b0315612b6a5760016003811115612a4c57612a4b613d8c565b5b826003811115612a5f57612a5e613d8c565b5b03612a96576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612aaa57612aa9613d8c565b5b826003811115612abd57612abc613d8c565b5b03612b0157805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612af891906130b1565b60405180910390fd5b600380811115612b1457612b13613d8c565b5b826003811115612b2757612b26613d8c565b5b03612b6957806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612b609190612fbe565b60405180910390fd5b5b5050565b612b766127f7565b612b81838383612bf8565b505050565b60605f612b9283612e11565b90505f602067ffffffffffffffff811115612bb057612baf6139a1565b5b6040519080825280601f01601f191660200182016040528015612be25781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612c48578060025f828254612c3c9190613db9565b92505081905550612d16565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612cd1578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612cc893929190613c0e565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d5d578060025f8282540392505081905550612da7565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612e0491906130b1565b60405180910390a3505050565b5f5f60ff835f1c169050601f811115612e56576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612e9781612e63565b8114612ea1575f5ffd5b50565b5f81359050612eb281612e8e565b92915050565b5f60208284031215612ecd57612ecc612e5f565b5b5f612eda84828501612ea4565b91505092915050565b5f8115159050919050565b612ef781612ee3565b82525050565b5f602082019050612f105f830184612eee565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612f5882612f16565b612f628185612f20565b9350612f72818560208601612f30565b612f7b81612f3e565b840191505092915050565b5f6020820190508181035f830152612f9e8184612f4e565b905092915050565b5f819050919050565b612fb881612fa6565b82525050565b5f602082019050612fd15f830184612faf565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61300082612fd7565b9050919050565b61301081612ff6565b811461301a575f5ffd5b50565b5f8135905061302b81613007565b92915050565b5f819050919050565b61304381613031565b811461304d575f5ffd5b50565b5f8135905061305e8161303a565b92915050565b5f5f6040838503121561307a57613079612e5f565b5b5f6130878582860161301d565b925050602061309885828601613050565b9150509250929050565b6130ab81613031565b82525050565b5f6020820190506130c45f8301846130a2565b92915050565b5f5f5f606084860312156130e1576130e0612e5f565b5b5f6130ee8682870161301d565b93505060206130ff8682870161301d565b925050604061311086828701613050565b9150509250925092565b61312381612fa6565b811461312d575f5ffd5b50565b5f8135905061313e8161311a565b92915050565b5f6020828403121561315957613158612e5f565b5b5f61316684828501613130565b91505092915050565b5f5f6040838503121561318557613184612e5f565b5b5f61319285828601613130565b92505060206131a38582860161301d565b9150509250929050565b5f60ff82169050919050565b6131c2816131ad565b82525050565b5f6020820190506131db5f8301846131b9565b92915050565b5f61ffff82169050919050565b6131f7816131e1565b8114613201575f5ffd5b50565b5f81359050613212816131ee565b92915050565b5f5f5f6060848603121561322f5761322e612e5f565b5b5f61323c86828701613204565b935050602061324d86828701613204565b925050604061325e86828701613204565b9150509250925092565b5f6020828403121561327d5761327c612e5f565b5b5f61328a84828501613050565b91505092915050565b5f602082840312156132a8576132a7612e5f565b5b5f6132b58482850161301d565b91505092915050565b6132c7816131e1565b82525050565b5f6020820190506132e05f8301846132be565b92915050565b5f602082840312156132fb576132fa612e5f565b5b5f61330884828501613204565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61334581613311565b82525050565b61335481612ff6565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61338c81613031565b82525050565b5f61339d8383613383565b60208301905092915050565b5f602082019050919050565b5f6133bf8261335a565b6133c98185613364565b93506133d483613374565b805f5b838110156134045781516133eb8882613392565b97506133f6836133a9565b9250506001810190506133d7565b5085935050505092915050565b5f60e0820190506134245f83018a61333c565b81810360208301526134368189612f4e565b9050818103604083015261344a8188612f4e565b905061345960608301876130a2565b613466608083018661334b565b61347360a0830185612faf565b81810360c083015261348581846133b5565b905098975050505050505050565b61349c816131ad565b81146134a6575f5ffd5b50565b5f813590506134b781613493565b92915050565b5f5f5f5f5f5f5f60e0888a0312156134d8576134d7612e5f565b5b5f6134e58a828b0161301d565b97505060206134f68a828b0161301d565b96505060406135078a828b01613050565b95505060606135188a828b01613050565b94505060806135298a828b016134a9565b93505060a061353a8a828b01613130565b92505060c061354b8a828b01613130565b91505092959891949750929550565b5f5f604083850312156135705761356f612e5f565b5b5f61357d8582860161301d565b925050602061358e8582860161301d565b9150509250929050565b5f6020820190506135ab5f83018461334b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806135f557607f821691505b602082108103613608576136076135b1565b5b50919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320615f8201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b5f613668602883612f20565b91506136738261360e565b604082019050919050565b5f6020820190508181035f8301526136958161365c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6136d382613031565b91506136de83613031565b92508282039050818111156136f6576136f561369c565b5b92915050565b7f474c44533a206275792074617820697320746f6f2068696768210000000000005f82015250565b5f613730601a83612f20565b915061373b826136fc565b602082019050919050565b5f6020820190508181035f83015261375d81613724565b9050919050565b7f474c44533a2073656c6c2074617820697320746f6f20686967682100000000005f82015250565b5f613798601b83612f20565b91506137a382613764565b602082019050919050565b5f6020820190508181035f8301526137c58161378c565b9050919050565b7f474c44533a207472616e736665722074617820697320746f6f206869676821005f82015250565b5f613800601f83612f20565b915061380b826137cc565b602082019050919050565b5f6020820190508181035f83015261382d816137f4565b9050919050565b5f6060820190506138475f8301866132be565b61385460208301856132be565b61386160408301846132be565b949350505050565b7f474c44533a205377617056325061697220616c726561647920616464656400005f82015250565b5f61389d601e83612f20565b91506138a882613869565b602082019050919050565b5f6020820190508181035f8301526138ca81613891565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f2068696768215f82015250565b5f613905602083612f20565b9150613910826138d1565b602082019050919050565b5f6020820190508181035f830152613932816138f9565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f206c6f7721005f82015250565b5f61396d601f83612f20565b915061397882613939565b602082019050919050565b5f6020820190508181035f83015261399a81613961565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f474c44533a2043616e6e6f74207365742074617820726563656976657220746f5f8201527f20746865207a65726f2061646472657373210000000000000000000000000000602082015250565b5f613a28603283612f20565b9150613a33826139ce565b604082019050919050565b5f6020820190508181035f830152613a5581613a1c565b9050919050565b5f60c082019050613a6f5f830189612faf565b613a7c602083018861334b565b613a89604083018761334b565b613a9660608301866130a2565b613aa360808301856130a2565b613ab060a08301846130a2565b979650505050505050565b5f604082019050613ace5f83018561334b565b613adb602083018461334b565b9392505050565b5f613aec82613031565b9150613af783613031565b9250828202613b0581613031565b91508282048414831517613b1c57613b1b61369c565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613b5a82613031565b9150613b6583613031565b925082613b7557613b74613b23565b5b828204905092915050565b7f474c44533a20427579206578636565647320627579206c696d69742025206f665f8201527f20746f74616c20737570706c7900000000000000000000000000000000000000602082015250565b5f613bda602d83612f20565b9150613be582613b80565b604082019050919050565b5f6020820190508181035f830152613c0781613bce565b9050919050565b5f606082019050613c215f83018661334b565b613c2e60208301856130a2565b613c3b60408301846130a2565b949350505050565b7f474c44533a20746178526563656976657220697320746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f613c9d602583612f20565b9150613ca882613c43565b604082019050919050565b5f6020820190508181035f830152613cca81613c91565b9050919050565b5f604082019050613ce45f83018561334b565b613cf16020830184612faf565b9392505050565b5f60a082019050613d0b5f830188612faf565b613d186020830187612faf565b613d256040830186612faf565b613d3260608301856130a2565b613d3f608083018461334b565b9695505050505050565b5f608082019050613d5c5f830187612faf565b613d6960208301866131b9565b613d766040830185612faf565b613d836060830184612faf565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f613dc382613031565b9150613dce83613031565b9250828201905080821115613de657613de561369c565b5b9291505056fea2646970667358221220d7ae364ebf38f1292ad96706abfb172fe0c3b90d5b165210e3b69f8aacc4dccd64736f6c634300081c0033

Deployed Bytecode Sourcemap

166387:7826:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35670:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13035:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166766:56;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;15328:190;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14137:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;169100:432;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36950:122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37382:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;13988:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172398:466;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;150192:114;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;38519:251;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;168031:77;;;:::i;:::-;;168116:107;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;23014:89;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;173197:259;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166960:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;25506:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172872:156;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14299:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;168347:112;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;173588:240;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;23432:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;149934:145;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;167950:73;;;:::i;:::-;;144578:580;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;35966:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13245:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;167038:47;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35278:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;168697:156;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173464:116;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166864:23;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166925:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172143:247;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166894:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;149180:695;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166697:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37813:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14867:142;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173036:153;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166549:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166831:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166618:72;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;168231:108;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;165614:121;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35670:204;35755:4;35794:32;35779:47;;;:11;:47;;;;:87;;;;35830:36;35854:11;35830:23;:36::i;:::-;35779:87;35772:94;;35670:204;;;:::o;13035:91::-;13080:13;13113:5;13106:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13035:91;:::o;166766:56::-;166801:21;166766:56;:::o;15328:190::-;15401:4;15418:13;15434:12;:10;:12::i;:::-;15418:28;;15457:31;15466:5;15473:7;15482:5;15457:8;:31::i;:::-;15506:4;15499:11;;;15328:190;;;;:::o;14137:99::-;14189:7;14216:12;;14209:19;;14137:99;:::o;169100:432::-;169189:4;169249:24;169276:27;169286:4;169292:10;169276:9;:27::i;:::-;169249:54;;169342:6;169322:16;:26;;169314:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;169404:53;169413:4;169419:10;169450:6;169431:16;:25;;;;:::i;:::-;169404:8;:53::i;:::-;169470:32;169485:4;169491:2;169495:6;169470:14;:32::i;:::-;169520:4;169513:11;;;169100:432;;;;;:::o;36950:122::-;37015:7;37042:6;:12;37049:4;37042:12;;;;;;;;;;;:22;;;37035:29;;36950:122;;;:::o;37382:138::-;37456:18;37469:4;37456:12;:18::i;:::-;35562:16;35573:4;35562:10;:16::i;:::-;37487:25:::1;37498:4;37504:7;37487:10;:25::i;:::-;;37382:138:::0;;;:::o;13988:84::-;14037:5;14062:2;14055:9;;13988:84;:::o;172398:466::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;172524:4:::1;172514:6;:14;;;;172506:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;172589:4;172578:7;:15;;;;172570:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;172659:4;172644:11;:19;;;;172636:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;172724:6;172712:9;;:18;;;;;;;;;;;;;;;;;;172754:7;172741:10;;:20;;;;;;;;;;;;;;;;;;172789:11;172772:14;;:28;;;;;;;;;;;;;;;;;;172818:38;172827:6;172835:7;172844:11;172818:38;;;;;;;;:::i;:::-;;;;;;;;172398:466:::0;;;;:::o;150192:114::-;150251:7;150278:20;:18;:20::i;:::-;150271:27;;150192:114;:::o;38519:251::-;38635:12;:10;:12::i;:::-;38613:34;;:18;:34;;;38609:104;;38671:30;;;;;;;;;;;;;;38609:104;38725:37;38737:4;38743:18;38725:11;:37::i;:::-;;38519:251;;:::o;168031:77::-;166587:24;35562:16;35573:4;35562:10;:16::i;:::-;168090:10:::1;:8;:10::i;:::-;168031:77:::0;:::o;168116:107::-;166735:24;35562:16;35573:4;35562:10;:16::i;:::-;168198:17:::1;168204:2;168208:6;168198:5;:17::i;:::-;168116:107:::0;;;:::o;23014:89::-;23069:26;23075:12;:10;:12::i;:::-;23089:5;23069;:26::i;:::-;23014:89;:::o;173197:259::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;173294:33:::1;173315:11;173294;:20;;:33;;;;:::i;:::-;173293:34;173285:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;173373:28;173389:11;173373;:15;;:28;;;;:::i;:::-;;173436:11;173417:31;;;;;;;;;;;;173197:259:::0;;:::o;166960:22::-;;;;;;;;;;;;;:::o;25506:86::-;25553:4;25577:7;;;;;;;;;;;25570:14;;25506:86;:::o;172872:156::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;172977:4:::1;172951:15;:23;172967:6;172951:23;;;;;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;173013:6;172997:23;;;;;;;;;;;;172872:156:::0;;:::o;14299:118::-;14364:7;14391:9;:18;14401:7;14391:18;;;;;;;;;;;;;;;;14384:25;;14299:118;;;:::o;168347:112::-;166661:29;35562:16;35573:4;35562:10;:16::i;:::-;168430:21:::1;168443:7;168430:12;:21::i;:::-;168347:112:::0;;:::o;173588:240::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;173691:3:::1;173676:11;:18;;;;173668:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;173757:1;173743:11;:15;;;173735:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;173809:11;173798:8;;:22;;;;;;;;;;;;;;;;;;173588:240:::0;;:::o;23432:161::-;23508:45;23524:7;23533:12;:10;:12::i;:::-;23547:5;23508:15;:45::i;:::-;23564:21;23570:7;23579:5;23564;:21::i;:::-;23432:161;;:::o;149934:145::-;150025:7;150052:19;150065:5;150052:12;:19::i;:::-;150045:26;;149934:145;;;:::o;167950:73::-;166587:24;35562:16;35573:4;35562:10;:16::i;:::-;168007:8:::1;:6;:8::i;:::-;167950:73:::0;:::o;144578:580::-;144681:13;144709:18;144742:21;144778:15;144808:25;144848:12;144875:27;144983:13;:11;:13::i;:::-;145011:16;:14;:16::i;:::-;145042:13;145078:4;145106:1;145098:10;;145137:1;145123:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144930:220;;;;;;;;;;;;;;;;;;;;;144578:580;;;;;;;:::o;35966:138::-;36043:4;36067:6;:12;36074:4;36067:12;;;;;;;;;;;:20;;:29;36088:7;36067:29;;;;;;;;;;;;;;;;;;;;;;;;;36060:36;;35966:138;;;;:::o;13245:95::-;13292:13;13325:7;13318:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13245:95;:::o;167038:47::-;;;;;;;;;;;;;;;;;;;;;;:::o;35278:49::-;35323:4;35278:49;;;:::o;168697:156::-;168768:4;168785:38;168800:10;168812:2;168816:6;168785:14;:38::i;:::-;168841:4;168834:11;;168697:156;;;;:::o;173464:116::-;173522:4;173546:26;173567:4;173546:11;:20;;:26;;;;:::i;:::-;173539:33;;173464:116;;;:::o;166864:23::-;;;;;;;;;;;;;:::o;166925:28::-;;;;;;;;;;;;;:::o;172143:247::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;172252:1:::1;172232:22;;:8;:22;;::::0;172224:85:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;172334:8;172320:11;;:22;;;;;;;;;;;;;;;;;;172373:8;172358:24;;;;;;;;;;;;172143:247:::0;;:::o;166894:24::-;;;;;;;;;;;;;:::o;149180:695::-;149410:8;149392:15;:26;149388:99;;;149466:8;149442:33;;;;;;;;;;;:::i;:::-;;;;;;;;149388:99;149499:18;148499:95;149558:5;149565:7;149574:5;149581:16;149591:5;149581:9;:16::i;:::-;149599:8;149530:78;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;149520:89;;;;;;149499:110;;149622:12;149637:28;149654:10;149637:16;:28::i;:::-;149622:43;;149678:14;149695:28;149709:4;149715:1;149718;149721;149695:13;:28::i;:::-;149678:45;;149748:5;149738:15;;:6;:15;;;149734:90;;149798:6;149806:5;149777:35;;;;;;;;;;;;:::i;:::-;;;;;;;;149734:90;149836:31;149845:5;149852:7;149861:5;149836:8;:31::i;:::-;149377:498;;;149180:695;;;;;;;:::o;166697:62::-;166735:24;166697:62;:::o;37813:140::-;37888:18;37901:4;37888:12;:18::i;:::-;35562:16;35573:4;35562:10;:16::i;:::-;37919:26:::1;37931:4;37937:7;37919:11;:26::i;:::-;;37813:140:::0;;;:::o;14867:142::-;14947:7;14974:11;:18;14986:5;14974:18;;;;;;;;;;;;;;;:27;14993:7;14974:27;;;;;;;;;;;;;;;;14967:34;;14867:142;;;;:::o;173036:153::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;173139:5:::1;173113:15;:23;173129:6;173113:23;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;173174:6;173160:21;;;;;;;;;;;;173036:153:::0;;:::o;166549:62::-;166587:24;166549:62;:::o;166831:26::-;;;;;;;;;;;;;:::o;166618:72::-;166661:29;166618:72;:::o;168231:108::-;166661:29;35562:16;35573:4;35562:10;:16::i;:::-;168312:19:::1;168323:7;168312:10;:19::i;:::-;168231:108:::0;;:::o;165614:121::-;165678:4;165704:11;:21;165716:8;165704:21;;;;;;;;;;;;;;;;;;;;;;;;;165697:28;;165614:121;;;:::o;33000:148::-;33076:4;33115:25;33100:40;;;:11;:40;;;;33093:47;;33000:148;;;:::o;4322:98::-;4375:7;4402:10;4395:17;;4322:98;:::o;20187:130::-;20272:37;20281:5;20288:7;20297:5;20304:4;20272:8;:37::i;:::-;20187:130;;;:::o;169780:1433::-;169957:15;:21;169973:4;169957:21;;;;;;;;;;;;;;;;;;;;;;;;;:44;;;;169982:15;:19;169998:2;169982:19;;;;;;;;;;;;;;;;;;;;;;;;;169957:44;169953:125;;;170018:27;170028:4;170034:2;170038:6;170018:9;:27::i;:::-;170060:7;;169953:125;170163:24;170184:2;170163:11;:20;;:24;;;;:::i;:::-;170159:1047;;;170221:1;170208:10;;;;;;;;;;;:14;;;170204:167;;;170243:44;170258:4;170264:2;170268:6;170276:10;;;;;;;;;;;170243:14;:44::i;:::-;170204:167;;;170328:27;170338:4;170344:2;170348:6;170328:9;:27::i;:::-;170204:167;170159:1047;;;170475:26;170496:4;170475:11;:20;;:26;;;;:::i;:::-;170471:735;;;170648:3;170636:8;;;;;;;;;;;170620:24;;:13;:11;:13::i;:::-;:24;;;;:::i;:::-;170619:32;;;;:::i;:::-;170609:6;:42;;170583:149;;;;;;;;;;;;:::i;:::-;;;;;;;;;170765:1;170753:9;;;;;;;;;;;:13;;;170749:165;;;170787:43;170802:4;170808:2;170812:6;170820:9;;;;;;;;;;;170787:14;:43::i;:::-;170749:165;;;170871:27;170881:4;170887:2;170891:6;170871:9;:27::i;:::-;170749:165;170471:735;;;171003:1;170986:14;;;;;;;;;;;:18;;;170982:224;;;171021:48;171036:4;171042:2;171046:6;171054:14;;;;;;;;;;;171021;:48::i;:::-;170982:224;;;171167:27;171177:4;171183:2;171187:6;171167:9;:27::i;:::-;170982:224;170471:735;170159:1047;169780:1433;;;;:::o;36319:105::-;36386:30;36397:4;36403:12;:10;:12::i;:::-;36386:10;:30::i;:::-;36319:105;:::o;39396:324::-;39473:4;39495:22;39503:4;39509:7;39495;:22::i;:::-;39490:223;;39566:4;39534:6;:12;39541:4;39534:12;;;;;;;;;;;:20;;:29;39555:7;39534:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;39617:12;:10;:12::i;:::-;39590:40;;39608:7;39590:40;;39602:4;39590:40;;;;;;;;;;39652:4;39645:11;;;;39490:223;39696:5;39689:12;;39396:324;;;;;:::o;143245:268::-;143298:7;143339:11;143322:28;;143330:4;143322:28;;;:63;;;;;143371:14;143354:13;:31;143322:63;143318:188;;;143409:22;143402:29;;;;143318:188;143471:23;:21;:23::i;:::-;143464:30;;143245:268;;:::o;39964:325::-;40042:4;40063:22;40071:4;40077:7;40063;:22::i;:::-;40059:223;;;40134:5;40102:6;:12;40109:4;40102:12;;;;;;;;;;;:20;;:29;40123:7;40102:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;40186:12;:10;:12::i;:::-;40159:40;;40177:7;40159:40;;40171:4;40159:40;;;;;;;;;;40221:4;40214:11;;;;40059:223;40265:5;40258:12;;39964:325;;;;;:::o;26407:120::-;25370:16;:14;:16::i;:::-;26476:5:::1;26466:7;;:15;;;;;;;;;;;;;;;;;;26497:22;26506:12;:10;:12::i;:::-;26497:22;;;;;;:::i;:::-;;;;;;;;26407:120::o:0;18882:213::-;18972:1;18953:21;;:7;:21;;;18949:93;;19027:1;18998:32;;;;;;;;;;;:::i;:::-;;;;;;;;18949:93;19052:35;19068:1;19072:7;19081:5;19052:7;:35::i;:::-;18882:213;;:::o;19423:211::-;19513:1;19494:21;;:7;:21;;;19490:91;;19566:1;19539:30;;;;;;;;;;;:::i;:::-;;;;;;;;19490:91;19591:35;19599:7;19616:1;19620:5;19591:7;:35::i;:::-;19423:211;;:::o;159458:167::-;159538:4;159562:55;159572:3;:10;;159608:5;159592:23;;159584:32;;159562:9;:55::i;:::-;159555:62;;159458:167;;;;:::o;158886:152::-;158956:4;158980:50;158985:3;:10;;159021:5;159005:23;;158997:32;;158980:4;:50::i;:::-;158973:57;;158886:152;;;;:::o;166149:150::-;166243:5;166219:11;:21;166231:8;166219:21;;;;;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;166280:8;166266:23;;;;;;;;;;;;166149:150;:::o;21919:487::-;22019:24;22046:25;22056:5;22063:7;22046:9;:25::i;:::-;22019:52;;22106:17;22086:16;:37;22082:317;;22163:5;22144:16;:24;22140:132;;;22223:7;22232:16;22250:5;22196:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;22140:132;22315:57;22324:5;22331:7;22359:5;22340:16;:24;22366:5;22315:8;:57::i;:::-;22082:317;22008:398;21919:487;;;:::o;146678:109::-;146738:7;146765;:14;146773:5;146765:14;;;;;;;;;;;;;;;;146758:21;;146678:109;;;:::o;26148:118::-;25111:19;:17;:19::i;:::-;26218:4:::1;26208:7;;:14;;;;;;;;;;;;;;;;;;26238:20;26245:12;:10;:12::i;:::-;26238:20;;;;;;:::i;:::-;;;;;;;;26148:118::o:0;145487:128::-;145533:13;145566:41;145593:13;145566:5;:26;;:41;;;;:::i;:::-;145559:48;;145487:128;:::o;145950:137::-;145999:13;146032:47;146062:16;146032:8;:29;;:47;;;;:::i;:::-;146025:54;;145950:137;:::o;146908:402::-;146968:7;147275;:14;147283:5;147275:14;;;;;;;;;;;;;;;;:16;;;;;;;;;;;;147268:23;;146908:402;;;:::o;144344:178::-;144421:7;144448:66;144481:20;:18;:20::i;:::-;144503:10;144448:32;:66::i;:::-;144441:73;;144344:178;;;:::o;51330:264::-;51415:7;51436:17;51455:18;51475:16;51495:25;51506:4;51512:1;51515;51518;51495:10;:25::i;:::-;51435:85;;;;;;51531:28;51543:5;51550:8;51531:11;:28::i;:::-;51577:9;51570:16;;;;;51330:264;;;;;;:::o;165859:145::-;165951:4;165927:11;:21;165939:8;165927:21;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;165985:8;165973:21;;;;;;;;;;;;165859:145;:::o;21184:443::-;21314:1;21297:19;;:5;:19;;;21293:91;;21369:1;21340:32;;;;;;;;;;;:::i;:::-;;;;;;;;21293:91;21417:1;21398:21;;:7;:21;;;21394:92;;21471:1;21443:31;;;;;;;;;;;:::i;:::-;;;;;;;;21394:92;21526:5;21496:11;:18;21508:5;21496:18;;;;;;;;;;;;;;;:27;21515:7;21496:27;;;;;;;;;;;;;;;:35;;;;21546:9;21542:78;;;21593:7;21577:31;;21586:5;21577:31;;;21602:5;21577:31;;;;;;:::i;:::-;;;;;;;;21542:78;21184:443;;;;:::o;16762:308::-;16862:1;16846:18;;:4;:18;;;16842:88;;16915:1;16888:30;;;;;;;;;;;:::i;:::-;;;;;;;;16842:88;16958:1;16944:16;;:2;:16;;;16940:88;;17013:1;16984:32;;;;;;;;;;;:::i;:::-;;;;;;;;16940:88;17038:24;17046:4;17052:2;17056:5;17038:7;:24::i;:::-;16762:308;;;:::o;171445:550::-;171588:17;171628:5;171618:6;171609:15;;:6;:15;;;;:::i;:::-;171608:25;;;;:::i;:::-;171588:45;;171644:18;171674:9;171665:6;:18;;;;:::i;:::-;171644:39;;171727:1;171704:25;;:11;;;;;;;;;;;:25;;;171696:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;171838:39;171848:4;171854:11;;;;;;;;;;;171867:9;171838;:39::i;:::-;171956:31;171966:4;171972:2;171976:10;171956:9;:31::i;:::-;171577:418;;171445:550;;;;:::o;36560:201::-;36649:22;36657:4;36663:7;36649;:22::i;:::-;36644:110;;36728:7;36737:4;36695:47;;;;;;;;;;;;:::i;:::-;;;;;;;;36644:110;36560:201;;:::o;143521:181::-;143576:7;141437:95;143635:11;143648:14;143664:13;143687:4;143613:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;143603:91;;;;;;143596:98;;143521:181;:::o;25874:130::-;25938:8;:6;:8::i;:::-;25933:64;;25970:15;;;;;;;;;;;;;;25933:64;25874:130::o;174040:170::-;174172:30;174186:4;174192:2;174196:5;174172:13;:30::i;:::-;174040:170;;;:::o;154739:131::-;154812:4;154861:1;154836:3;:14;;:21;154851:5;154836:21;;;;;;;;;;;;:26;;154829:33;;154739:131;;;;:::o;152661:416::-;152724:4;152746:21;152756:3;152761:5;152746:9;:21::i;:::-;152741:329;;152784:3;:11;;152801:5;152784:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;152969:3;:11;;:18;;;;152945:3;:14;;:21;152960:5;152945:21;;;;;;;;;;;:42;;;;153009:4;153002:11;;;;152741:329;153053:5;153046:12;;152661:416;;;;;:::o;25665:132::-;25731:8;:6;:8::i;:::-;25727:63;;;25763:15;;;;;;;;;;;;;;25727:63;25665:132::o;137702:273::-;137796:13;135676:66;137855:17;;137845:5;137826:46;137822:146;;137896:15;137905:5;137896:8;:15::i;:::-;137889:22;;;;137822:146;137951:5;137944:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137702:273;;;;;:::o;129510:382::-;129603:14;129687:4;129681:11;129718:10;129713:3;129706:23;129766:15;129759:4;129754:3;129750:14;129743:39;129819:10;129812:4;129807:3;129803:14;129796:34;129869:4;129864:3;129854:20;129844:30;;129655:230;129510:382;;;;:::o;49614:1577::-;49745:17;49764:16;49782:14;50709:66;50704:1;50696:10;;:79;50692:166;;;50808:1;50812:30;50844:1;50792:54;;;;;;;;50692:166;50955:14;50972:24;50982:4;50988:1;50991;50994;50972:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50955:41;;51029:1;51011:20;;:6;:20;;;51007:115;;51064:1;51068:29;51107:1;51099:10;;51048:62;;;;;;;;;51007:115;51142:6;51150:20;51180:1;51172:10;;51134:49;;;;;;;49614:1577;;;;;;;;;:::o;51732:542::-;51828:20;51819:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;51815:452;51865:7;51815:452;51926:29;51917:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;51913:354;;51979:23;;;;;;;;;;;;;;51913:354;52033:35;52024:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;52020:247;;52128:8;52120:17;;52092:46;;;;;;;;;;;:::i;:::-;;;;;;;;52020:247;52169:30;52160:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;52156:111;;52246:8;52223:32;;;;;;;;;;;:::i;:::-;;;;;;;;52156:111;51732:542;;;:::o;27638:147::-;25111:19;:17;:19::i;:::-;27747:30:::1;27761:4;27767:2;27771:5;27747:13;:30::i;:::-;27638:147:::0;;;:::o;136385:387::-;136444:13;136470:11;136484:16;136495:4;136484:10;:16::i;:::-;136470:30;;136590:17;136621:2;136610:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136590:34;;136687:3;136682;136675:16;136728:4;136721;136716:3;136712:14;136705:28;136761:3;136754:10;;;;136385:387;;;:::o;17394:1135::-;17500:1;17484:18;;:4;:18;;;17480:552;;17638:5;17622:12;;:21;;;;;;;:::i;:::-;;;;;;;;17480:552;;;17676:19;17698:9;:15;17708:4;17698:15;;;;;;;;;;;;;;;;17676:37;;17746:5;17732:11;:19;17728:117;;;17804:4;17810:11;17823:5;17779:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;17728:117;18000:5;17986:11;:19;17968:9;:15;17978:4;17968:15;;;;;;;;;;;;;;;:37;;;;17661:371;17480:552;18062:1;18048:16;;:2;:16;;;18044:435;;18230:5;18214:12;;:21;;;;;;;;;;;18044:435;;;18447:5;18430:9;:13;18440:2;18430:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;18044:435;18511:2;18496:25;;18505:4;18496:25;;;18515:5;18496:25;;;;;;:::i;:::-;;;;;;;;17394:1135;;;:::o;136849:251::-;136910:7;136930:14;136983:4;136974;136947:33;;:40;136930:57;;137011:2;137002:6;:11;136998:71;;;137037:20;;;;;;;;;;;;;;136998:71;137086:6;137079:13;;;136849:251;;;:::o;88:117:1:-;197:1;194;187:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:139::-;1887:6;1882:3;1877;1871:23;1928:1;1919:6;1914:3;1910:16;1903:27;1798:139;;;:::o;1943:102::-;1984:6;2035:2;2031:7;2026:2;2019:5;2015:14;2011:28;2001:38;;1943:102;;;:::o;2051:377::-;2139:3;2167:39;2200:5;2167:39;:::i;:::-;2222:71;2286:6;2281:3;2222:71;:::i;:::-;2215:78;;2302:65;2360:6;2355:3;2348:4;2341:5;2337:16;2302:65;:::i;:::-;2392:29;2414:6;2392:29;:::i;:::-;2387:3;2383:39;2376:46;;2143:285;2051:377;;;;:::o;2434:313::-;2547:4;2585:2;2574:9;2570:18;2562:26;;2634:9;2628:4;2624:20;2620:1;2609:9;2605:17;2598:47;2662:78;2735:4;2726:6;2662:78;:::i;:::-;2654:86;;2434:313;;;;:::o;2753:77::-;2790:7;2819:5;2808:16;;2753:77;;;:::o;2836:118::-;2923:24;2941:5;2923:24;:::i;:::-;2918:3;2911:37;2836:118;;:::o;2960:222::-;3053:4;3091:2;3080:9;3076:18;3068:26;;3104:71;3172:1;3161:9;3157:17;3148:6;3104:71;:::i;:::-;2960:222;;;;:::o;3188:126::-;3225:7;3265:42;3258:5;3254:54;3243:65;;3188:126;;;:::o;3320:96::-;3357:7;3386:24;3404:5;3386:24;:::i;:::-;3375:35;;3320:96;;;:::o;3422:122::-;3495:24;3513:5;3495:24;:::i;:::-;3488:5;3485:35;3475:63;;3534:1;3531;3524:12;3475:63;3422:122;:::o;3550:139::-;3596:5;3634:6;3621:20;3612:29;;3650:33;3677:5;3650:33;:::i;:::-;3550:139;;;;:::o;3695:77::-;3732:7;3761:5;3750:16;;3695:77;;;:::o;3778:122::-;3851:24;3869:5;3851:24;:::i;:::-;3844:5;3841:35;3831:63;;3890:1;3887;3880:12;3831:63;3778:122;:::o;3906:139::-;3952:5;3990:6;3977:20;3968:29;;4006:33;4033:5;4006:33;:::i;:::-;3906:139;;;;:::o;4051:474::-;4119:6;4127;4176:2;4164:9;4155:7;4151:23;4147:32;4144:119;;;4182:79;;:::i;:::-;4144:119;4302:1;4327:53;4372:7;4363:6;4352:9;4348:22;4327:53;:::i;:::-;4317:63;;4273:117;4429:2;4455:53;4500:7;4491:6;4480:9;4476:22;4455:53;:::i;:::-;4445:63;;4400:118;4051:474;;;;;:::o;4531:118::-;4618:24;4636:5;4618:24;:::i;:::-;4613:3;4606:37;4531:118;;:::o;4655:222::-;4748:4;4786:2;4775:9;4771:18;4763:26;;4799:71;4867:1;4856:9;4852:17;4843:6;4799:71;:::i;:::-;4655:222;;;;:::o;4883:619::-;4960:6;4968;4976;5025:2;5013:9;5004:7;5000:23;4996:32;4993:119;;;5031:79;;:::i;:::-;4993:119;5151:1;5176:53;5221:7;5212:6;5201:9;5197:22;5176:53;:::i;:::-;5166:63;;5122:117;5278:2;5304:53;5349:7;5340:6;5329:9;5325:22;5304:53;:::i;:::-;5294:63;;5249:118;5406:2;5432:53;5477:7;5468:6;5457:9;5453:22;5432:53;:::i;:::-;5422:63;;5377:118;4883:619;;;;;:::o;5508:122::-;5581:24;5599:5;5581:24;:::i;:::-;5574:5;5571:35;5561:63;;5620:1;5617;5610:12;5561:63;5508:122;:::o;5636:139::-;5682:5;5720:6;5707:20;5698:29;;5736:33;5763:5;5736:33;:::i;:::-;5636:139;;;;:::o;5781:329::-;5840:6;5889:2;5877:9;5868:7;5864:23;5860:32;5857:119;;;5895:79;;:::i;:::-;5857:119;6015:1;6040:53;6085:7;6076:6;6065:9;6061:22;6040:53;:::i;:::-;6030:63;;5986:117;5781:329;;;;:::o;6116:474::-;6184:6;6192;6241:2;6229:9;6220:7;6216:23;6212:32;6209:119;;;6247:79;;:::i;:::-;6209:119;6367:1;6392:53;6437:7;6428:6;6417:9;6413:22;6392:53;:::i;:::-;6382:63;;6338:117;6494:2;6520:53;6565:7;6556:6;6545:9;6541:22;6520:53;:::i;:::-;6510:63;;6465:118;6116:474;;;;;:::o;6596:86::-;6631:7;6671:4;6664:5;6660:16;6649:27;;6596:86;;;:::o;6688:112::-;6771:22;6787:5;6771:22;:::i;:::-;6766:3;6759:35;6688:112;;:::o;6806:214::-;6895:4;6933:2;6922:9;6918:18;6910:26;;6946:67;7010:1;6999:9;6995:17;6986:6;6946:67;:::i;:::-;6806:214;;;;:::o;7026:89::-;7062:7;7102:6;7095:5;7091:18;7080:29;;7026:89;;;:::o;7121:120::-;7193:23;7210:5;7193:23;:::i;:::-;7186:5;7183:34;7173:62;;7231:1;7228;7221:12;7173:62;7121:120;:::o;7247:137::-;7292:5;7330:6;7317:20;7308:29;;7346:32;7372:5;7346:32;:::i;:::-;7247:137;;;;:::o;7390:613::-;7464:6;7472;7480;7529:2;7517:9;7508:7;7504:23;7500:32;7497:119;;;7535:79;;:::i;:::-;7497:119;7655:1;7680:52;7724:7;7715:6;7704:9;7700:22;7680:52;:::i;:::-;7670:62;;7626:116;7781:2;7807:52;7851:7;7842:6;7831:9;7827:22;7807:52;:::i;:::-;7797:62;;7752:117;7908:2;7934:52;7978:7;7969:6;7958:9;7954:22;7934:52;:::i;:::-;7924:62;;7879:117;7390:613;;;;;:::o;8009:329::-;8068:6;8117:2;8105:9;8096:7;8092:23;8088:32;8085:119;;;8123:79;;:::i;:::-;8085:119;8243:1;8268:53;8313:7;8304:6;8293:9;8289:22;8268:53;:::i;:::-;8258:63;;8214:117;8009:329;;;;:::o;8344:::-;8403:6;8452:2;8440:9;8431:7;8427:23;8423:32;8420:119;;;8458:79;;:::i;:::-;8420:119;8578:1;8603:53;8648:7;8639:6;8628:9;8624:22;8603:53;:::i;:::-;8593:63;;8549:117;8344:329;;;;:::o;8679:115::-;8764:23;8781:5;8764:23;:::i;:::-;8759:3;8752:36;8679:115;;:::o;8800:218::-;8891:4;8929:2;8918:9;8914:18;8906:26;;8942:69;9008:1;8997:9;8993:17;8984:6;8942:69;:::i;:::-;8800:218;;;;:::o;9024:327::-;9082:6;9131:2;9119:9;9110:7;9106:23;9102:32;9099:119;;;9137:79;;:::i;:::-;9099:119;9257:1;9282:52;9326:7;9317:6;9306:9;9302:22;9282:52;:::i;:::-;9272:62;;9228:116;9024:327;;;;:::o;9357:149::-;9393:7;9433:66;9426:5;9422:78;9411:89;;9357:149;;;:::o;9512:115::-;9597:23;9614:5;9597:23;:::i;:::-;9592:3;9585:36;9512:115;;:::o;9633:118::-;9720:24;9738:5;9720:24;:::i;:::-;9715:3;9708:37;9633:118;;:::o;9757:114::-;9824:6;9858:5;9852:12;9842:22;;9757:114;;;:::o;9877:184::-;9976:11;10010:6;10005:3;9998:19;10050:4;10045:3;10041:14;10026:29;;9877:184;;;;:::o;10067:132::-;10134:4;10157:3;10149:11;;10187:4;10182:3;10178:14;10170:22;;10067:132;;;:::o;10205:108::-;10282:24;10300:5;10282:24;:::i;:::-;10277:3;10270:37;10205:108;;:::o;10319:179::-;10388:10;10409:46;10451:3;10443:6;10409:46;:::i;:::-;10487:4;10482:3;10478:14;10464:28;;10319:179;;;;:::o;10504:113::-;10574:4;10606;10601:3;10597:14;10589:22;;10504:113;;;:::o;10653:732::-;10772:3;10801:54;10849:5;10801:54;:::i;:::-;10871:86;10950:6;10945:3;10871:86;:::i;:::-;10864:93;;10981:56;11031:5;10981:56;:::i;:::-;11060:7;11091:1;11076:284;11101:6;11098:1;11095:13;11076:284;;;11177:6;11171:13;11204:63;11263:3;11248:13;11204:63;:::i;:::-;11197:70;;11290:60;11343:6;11290:60;:::i;:::-;11280:70;;11136:224;11123:1;11120;11116:9;11111:14;;11076:284;;;11080:14;11376:3;11369:10;;10777:608;;;10653:732;;;;:::o;11391:1215::-;11740:4;11778:3;11767:9;11763:19;11755:27;;11792:69;11858:1;11847:9;11843:17;11834:6;11792:69;:::i;:::-;11908:9;11902:4;11898:20;11893:2;11882:9;11878:18;11871:48;11936:78;12009:4;12000:6;11936:78;:::i;:::-;11928:86;;12061:9;12055:4;12051:20;12046:2;12035:9;12031:18;12024:48;12089:78;12162:4;12153:6;12089:78;:::i;:::-;12081:86;;12177:72;12245:2;12234:9;12230:18;12221:6;12177:72;:::i;:::-;12259:73;12327:3;12316:9;12312:19;12303:6;12259:73;:::i;:::-;12342;12410:3;12399:9;12395:19;12386:6;12342:73;:::i;:::-;12463:9;12457:4;12453:20;12447:3;12436:9;12432:19;12425:49;12491:108;12594:4;12585:6;12491:108;:::i;:::-;12483:116;;11391:1215;;;;;;;;;;:::o;12612:118::-;12683:22;12699:5;12683:22;:::i;:::-;12676:5;12673:33;12663:61;;12720:1;12717;12710:12;12663:61;12612:118;:::o;12736:135::-;12780:5;12818:6;12805:20;12796:29;;12834:31;12859:5;12834:31;:::i;:::-;12736:135;;;;:::o;12877:1199::-;12988:6;12996;13004;13012;13020;13028;13036;13085:3;13073:9;13064:7;13060:23;13056:33;13053:120;;;13092:79;;:::i;:::-;13053:120;13212:1;13237:53;13282:7;13273:6;13262:9;13258:22;13237:53;:::i;:::-;13227:63;;13183:117;13339:2;13365:53;13410:7;13401:6;13390:9;13386:22;13365:53;:::i;:::-;13355:63;;13310:118;13467:2;13493:53;13538:7;13529:6;13518:9;13514:22;13493:53;:::i;:::-;13483:63;;13438:118;13595:2;13621:53;13666:7;13657:6;13646:9;13642:22;13621:53;:::i;:::-;13611:63;;13566:118;13723:3;13750:51;13793:7;13784:6;13773:9;13769:22;13750:51;:::i;:::-;13740:61;;13694:117;13850:3;13877:53;13922:7;13913:6;13902:9;13898:22;13877:53;:::i;:::-;13867:63;;13821:119;13979:3;14006:53;14051:7;14042:6;14031:9;14027:22;14006:53;:::i;:::-;13996:63;;13950:119;12877:1199;;;;;;;;;;:::o;14082:474::-;14150:6;14158;14207:2;14195:9;14186:7;14182:23;14178:32;14175:119;;;14213:79;;:::i;:::-;14175:119;14333:1;14358:53;14403:7;14394:6;14383:9;14379:22;14358:53;:::i;:::-;14348:63;;14304:117;14460:2;14486:53;14531:7;14522:6;14511:9;14507:22;14486:53;:::i;:::-;14476:63;;14431:118;14082:474;;;;;:::o;14562:222::-;14655:4;14693:2;14682:9;14678:18;14670:26;;14706:71;14774:1;14763:9;14759:17;14750:6;14706:71;:::i;:::-;14562:222;;;;:::o;14790:180::-;14838:77;14835:1;14828:88;14935:4;14932:1;14925:15;14959:4;14956:1;14949:15;14976:320;15020:6;15057:1;15051:4;15047:12;15037:22;;15104:1;15098:4;15094:12;15125:18;15115:81;;15181:4;15173:6;15169:17;15159:27;;15115:81;15243:2;15235:6;15232:14;15212:18;15209:38;15206:84;;15262:18;;:::i;:::-;15206:84;15027:269;14976:320;;;:::o;15302:227::-;15442:34;15438:1;15430:6;15426:14;15419:58;15511:10;15506:2;15498:6;15494:15;15487:35;15302:227;:::o;15535:366::-;15677:3;15698:67;15762:2;15757:3;15698:67;:::i;:::-;15691:74;;15774:93;15863:3;15774:93;:::i;:::-;15892:2;15887:3;15883:12;15876:19;;15535:366;;;:::o;15907:419::-;16073:4;16111:2;16100:9;16096:18;16088:26;;16160:9;16154:4;16150:20;16146:1;16135:9;16131:17;16124:47;16188:131;16314:4;16188:131;:::i;:::-;16180:139;;15907:419;;;:::o;16332:180::-;16380:77;16377:1;16370:88;16477:4;16474:1;16467:15;16501:4;16498:1;16491:15;16518:194;16558:4;16578:20;16596:1;16578:20;:::i;:::-;16573:25;;16612:20;16630:1;16612:20;:::i;:::-;16607:25;;16656:1;16653;16649:9;16641:17;;16680:1;16674:4;16671:11;16668:37;;;16685:18;;:::i;:::-;16668:37;16518:194;;;;:::o;16718:176::-;16858:28;16854:1;16846:6;16842:14;16835:52;16718:176;:::o;16900:366::-;17042:3;17063:67;17127:2;17122:3;17063:67;:::i;:::-;17056:74;;17139:93;17228:3;17139:93;:::i;:::-;17257:2;17252:3;17248:12;17241:19;;16900:366;;;:::o;17272:419::-;17438:4;17476:2;17465:9;17461:18;17453:26;;17525:9;17519:4;17515:20;17511:1;17500:9;17496:17;17489:47;17553:131;17679:4;17553:131;:::i;:::-;17545:139;;17272:419;;;:::o;17697:177::-;17837:29;17833:1;17825:6;17821:14;17814:53;17697:177;:::o;17880:366::-;18022:3;18043:67;18107:2;18102:3;18043:67;:::i;:::-;18036:74;;18119:93;18208:3;18119:93;:::i;:::-;18237:2;18232:3;18228:12;18221:19;;17880:366;;;:::o;18252:419::-;18418:4;18456:2;18445:9;18441:18;18433:26;;18505:9;18499:4;18495:20;18491:1;18480:9;18476:17;18469:47;18533:131;18659:4;18533:131;:::i;:::-;18525:139;;18252:419;;;:::o;18677:181::-;18817:33;18813:1;18805:6;18801:14;18794:57;18677:181;:::o;18864:366::-;19006:3;19027:67;19091:2;19086:3;19027:67;:::i;:::-;19020:74;;19103:93;19192:3;19103:93;:::i;:::-;19221:2;19216:3;19212:12;19205:19;;18864:366;;;:::o;19236:419::-;19402:4;19440:2;19429:9;19425:18;19417:26;;19489:9;19483:4;19479:20;19475:1;19464:9;19460:17;19453:47;19517:131;19643:4;19517:131;:::i;:::-;19509:139;;19236:419;;;:::o;19661:430::-;19804:4;19842:2;19831:9;19827:18;19819:26;;19855:69;19921:1;19910:9;19906:17;19897:6;19855:69;:::i;:::-;19934:70;20000:2;19989:9;19985:18;19976:6;19934:70;:::i;:::-;20014;20080:2;20069:9;20065:18;20056:6;20014:70;:::i;:::-;19661:430;;;;;;:::o;20097:180::-;20237:32;20233:1;20225:6;20221:14;20214:56;20097:180;:::o;20283:366::-;20425:3;20446:67;20510:2;20505:3;20446:67;:::i;:::-;20439:74;;20522:93;20611:3;20522:93;:::i;:::-;20640:2;20635:3;20631:12;20624:19;;20283:366;;;:::o;20655:419::-;20821:4;20859:2;20848:9;20844:18;20836:26;;20908:9;20902:4;20898:20;20894:1;20883:9;20879:17;20872:47;20936:131;21062:4;20936:131;:::i;:::-;20928:139;;20655:419;;;:::o;21080:182::-;21220:34;21216:1;21208:6;21204:14;21197:58;21080:182;:::o;21268:366::-;21410:3;21431:67;21495:2;21490:3;21431:67;:::i;:::-;21424:74;;21507:93;21596:3;21507:93;:::i;:::-;21625:2;21620:3;21616:12;21609:19;;21268:366;;;:::o;21640:419::-;21806:4;21844:2;21833:9;21829:18;21821:26;;21893:9;21887:4;21883:20;21879:1;21868:9;21864:17;21857:47;21921:131;22047:4;21921:131;:::i;:::-;21913:139;;21640:419;;;:::o;22065:181::-;22205:33;22201:1;22193:6;22189:14;22182:57;22065:181;:::o;22252:366::-;22394:3;22415:67;22479:2;22474:3;22415:67;:::i;:::-;22408:74;;22491:93;22580:3;22491:93;:::i;:::-;22609:2;22604:3;22600:12;22593:19;;22252:366;;;:::o;22624:419::-;22790:4;22828:2;22817:9;22813:18;22805:26;;22877:9;22871:4;22867:20;22863:1;22852:9;22848:17;22841:47;22905:131;23031:4;22905:131;:::i;:::-;22897:139;;22624:419;;;:::o;23049:180::-;23097:77;23094:1;23087:88;23194:4;23191:1;23184:15;23218:4;23215:1;23208:15;23235:237;23375:34;23371:1;23363:6;23359:14;23352:58;23444:20;23439:2;23431:6;23427:15;23420:45;23235:237;:::o;23478:366::-;23620:3;23641:67;23705:2;23700:3;23641:67;:::i;:::-;23634:74;;23717:93;23806:3;23717:93;:::i;:::-;23835:2;23830:3;23826:12;23819:19;;23478:366;;;:::o;23850:419::-;24016:4;24054:2;24043:9;24039:18;24031:26;;24103:9;24097:4;24093:20;24089:1;24078:9;24074:17;24067:47;24131:131;24257:4;24131:131;:::i;:::-;24123:139;;23850:419;;;:::o;24275:775::-;24508:4;24546:3;24535:9;24531:19;24523:27;;24560:71;24628:1;24617:9;24613:17;24604:6;24560:71;:::i;:::-;24641:72;24709:2;24698:9;24694:18;24685:6;24641:72;:::i;:::-;24723;24791:2;24780:9;24776:18;24767:6;24723:72;:::i;:::-;24805;24873:2;24862:9;24858:18;24849:6;24805:72;:::i;:::-;24887:73;24955:3;24944:9;24940:19;24931:6;24887:73;:::i;:::-;24970;25038:3;25027:9;25023:19;25014:6;24970:73;:::i;:::-;24275:775;;;;;;;;;:::o;25056:332::-;25177:4;25215:2;25204:9;25200:18;25192:26;;25228:71;25296:1;25285:9;25281:17;25272:6;25228:71;:::i;:::-;25309:72;25377:2;25366:9;25362:18;25353:6;25309:72;:::i;:::-;25056:332;;;;;:::o;25394:410::-;25434:7;25457:20;25475:1;25457:20;:::i;:::-;25452:25;;25491:20;25509:1;25491:20;:::i;:::-;25486:25;;25546:1;25543;25539:9;25568:30;25586:11;25568:30;:::i;:::-;25557:41;;25747:1;25738:7;25734:15;25731:1;25728:22;25708:1;25701:9;25681:83;25658:139;;25777:18;;:::i;:::-;25658:139;25442:362;25394:410;;;;:::o;25810:180::-;25858:77;25855:1;25848:88;25955:4;25952:1;25945:15;25979:4;25976:1;25969:15;25996:185;26036:1;26053:20;26071:1;26053:20;:::i;:::-;26048:25;;26087:20;26105:1;26087:20;:::i;:::-;26082:25;;26126:1;26116:35;;26131:18;;:::i;:::-;26116:35;26173:1;26170;26166:9;26161:14;;25996:185;;;;:::o;26187:232::-;26327:34;26323:1;26315:6;26311:14;26304:58;26396:15;26391:2;26383:6;26379:15;26372:40;26187:232;:::o;26425:366::-;26567:3;26588:67;26652:2;26647:3;26588:67;:::i;:::-;26581:74;;26664:93;26753:3;26664:93;:::i;:::-;26782:2;26777:3;26773:12;26766:19;;26425:366;;;:::o;26797:419::-;26963:4;27001:2;26990:9;26986:18;26978:26;;27050:9;27044:4;27040:20;27036:1;27025:9;27021:17;27014:47;27078:131;27204:4;27078:131;:::i;:::-;27070:139;;26797:419;;;:::o;27222:442::-;27371:4;27409:2;27398:9;27394:18;27386:26;;27422:71;27490:1;27479:9;27475:17;27466:6;27422:71;:::i;:::-;27503:72;27571:2;27560:9;27556:18;27547:6;27503:72;:::i;:::-;27585;27653:2;27642:9;27638:18;27629:6;27585:72;:::i;:::-;27222:442;;;;;;:::o;27670:224::-;27810:34;27806:1;27798:6;27794:14;27787:58;27879:7;27874:2;27866:6;27862:15;27855:32;27670:224;:::o;27900:366::-;28042:3;28063:67;28127:2;28122:3;28063:67;:::i;:::-;28056:74;;28139:93;28228:3;28139:93;:::i;:::-;28257:2;28252:3;28248:12;28241:19;;27900:366;;;:::o;28272:419::-;28438:4;28476:2;28465:9;28461:18;28453:26;;28525:9;28519:4;28515:20;28511:1;28500:9;28496:17;28489:47;28553:131;28679:4;28553:131;:::i;:::-;28545:139;;28272:419;;;:::o;28697:332::-;28818:4;28856:2;28845:9;28841:18;28833:26;;28869:71;28937:1;28926:9;28922:17;28913:6;28869:71;:::i;:::-;28950:72;29018:2;29007:9;29003:18;28994:6;28950:72;:::i;:::-;28697:332;;;;;:::o;29035:664::-;29240:4;29278:3;29267:9;29263:19;29255:27;;29292:71;29360:1;29349:9;29345:17;29336:6;29292:71;:::i;:::-;29373:72;29441:2;29430:9;29426:18;29417:6;29373:72;:::i;:::-;29455;29523:2;29512:9;29508:18;29499:6;29455:72;:::i;:::-;29537;29605:2;29594:9;29590:18;29581:6;29537:72;:::i;:::-;29619:73;29687:3;29676:9;29672:19;29663:6;29619:73;:::i;:::-;29035:664;;;;;;;;:::o;29705:545::-;29878:4;29916:3;29905:9;29901:19;29893:27;;29930:71;29998:1;29987:9;29983:17;29974:6;29930:71;:::i;:::-;30011:68;30075:2;30064:9;30060:18;30051:6;30011:68;:::i;:::-;30089:72;30157:2;30146:9;30142:18;30133:6;30089:72;:::i;:::-;30171;30239:2;30228:9;30224:18;30215:6;30171:72;:::i;:::-;29705:545;;;;;;;:::o;30256:180::-;30304:77;30301:1;30294:88;30401:4;30398:1;30391:15;30425:4;30422:1;30415:15;30442:191;30482:3;30501:20;30519:1;30501:20;:::i;:::-;30496:25;;30535:20;30553:1;30535:20;:::i;:::-;30530:25;;30578:1;30575;30571:9;30564:16;;30599:3;30596:1;30593:10;30590:36;;;30606:18;;:::i;:::-;30590:36;30442:191;;;;:::o

Swarm Source

ipfs://d7ae364ebf38f1292ad96706abfb172fe0c3b90d5b165210e3b69f8aacc4dccd
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.