ETH Price: $3,266.88 (+5.01%)
 

Overview

Max Total Supply

0 AnglePerp

Holders

0

Total Transfers

-

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
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:
PerpetualManagerFront

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 283 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-11-01
*/

// Sources flattened with hardhat v2.6.7 https://hardhat.org

// File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected]

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.0;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}


// File @openzeppelin/contracts-upgradeable/utils/[email protected]



pragma solidity ^0.8.0;

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

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
    uint256[50] private __gap;
}


// File @openzeppelin/contracts-upgradeable/security/[email protected]



pragma solidity ^0.8.0;


/**
 * @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 PausableUpgradeable is Initializable, ContextUpgradeable {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

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

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal initializer {
        __Context_init_unchained();
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal initializer {
        _paused = false;
    }

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

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

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

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

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


// File @openzeppelin/contracts-upgradeable/token/ERC721/[email protected]



pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721ReceiverUpgradeable {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}


// File @openzeppelin/contracts-upgradeable/utils/introspection/[email protected]



pragma solidity ^0.8.0;

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


// File @openzeppelin/contracts-upgradeable/token/ERC721/[email protected]



pragma solidity ^0.8.0;

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721Upgradeable is IERC165Upgradeable {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}


// File @openzeppelin/contracts-upgradeable/utils/introspection/[email protected]



pragma solidity ^0.8.0;


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

    function __ERC165_init_unchained() internal initializer {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165Upgradeable).interfaceId;
    }
    uint256[50] private __gap;
}


// File @openzeppelin/contracts-upgradeable/utils/[email protected]



pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts-upgradeable/utils/[email protected]



pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library CountersUpgradeable {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}


// File @openzeppelin/contracts/token/ERC20/[email protected]



pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]



pragma solidity ^0.8.0;

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

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

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


// File @openzeppelin/contracts/utils/[email protected]



pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]



pragma solidity ^0.8.0;


/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// File @openzeppelin/contracts-upgradeable/utils/[email protected]



pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library StringsUpgradeable {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

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


// File contracts/interfaces/IAccessControl.sol



pragma solidity ^0.8.7;

/// @title IAccessControl
/// @author Forked from OpenZeppelin
/// @notice Interface for `AccessControl` contracts
interface IAccessControl {
    function hasRole(bytes32 role, address account) external view returns (bool);

    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    function grantRole(bytes32 role, address account) external;

    function revokeRole(bytes32 role, address account) external;

    function renounceRole(bytes32 role, address account) external;
}


// File contracts/external/AccessControlUpgradeable.sol



pragma solidity ^0.8.7;


/**
 * @dev This contract is fully forked from OpenZeppelin `AccessControlUpgradeable`.
 * The only difference is the removal of the ERC165 implementation as it's not
 * needed in Angle.
 *
 * 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:
 *
 * ```
 * 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}:
 *
 * ```
 * 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.
 */
abstract contract AccessControlUpgradeable is Initializable, IAccessControl {
    function __AccessControl_init() internal initializer {
        __AccessControl_init_unchained();
    }

    function __AccessControl_init_unchained() internal initializer {}

    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

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

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

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

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

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

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

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

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

        _revokeRole(role, account);
    }

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

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

    function _grantRole(bytes32 role, address account) internal {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, msg.sender);
        }
    }

    function _revokeRole(bytes32 role, address account) internal {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, msg.sender);
        }
    }

    uint256[49] private __gap;
}


// File contracts/interfaces/IFeeManager.sol



pragma solidity ^0.8.7;

/// @title IFeeManagerFunctions
/// @author Angle Core Team
/// @dev Interface for the `FeeManager` contract
interface IFeeManagerFunctions is IAccessControl {
    // ================================= Keepers ===================================

    function updateUsersSLP() external;

    function updateHA() external;

    // ================================= Governance ================================

    function deployCollateral(
        address[] memory governorList,
        address guardian,
        address _perpetualManager
    ) external;

    function setFees(
        uint256[] memory xArray,
        uint64[] memory yArray,
        uint8 typeChange
    ) external;

    function setHAFees(uint64 _haFeeDeposit, uint64 _haFeeWithdraw) external;
}

/// @title IFeeManager
/// @author Angle Core Team
/// @notice Previous interface with additionnal getters for public variables and mappings
/// @dev We need these getters as they are used in other contracts of the protocol
interface IFeeManager is IFeeManagerFunctions {
    function stableMaster() external view returns (address);

    function perpetualManager() external view returns (address);
}


// File @openzeppelin/contracts/utils/introspection/[email protected]



pragma solidity ^0.8.0;

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


// File contracts/interfaces/IERC721.sol



pragma solidity ^0.8.7;

interface IERC721 is IERC165 {
    function balanceOf(address owner) external view returns (uint256 balance);

    function ownerOf(uint256 tokenId) external view returns (address owner);

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    function approve(address to, uint256 tokenId) external;

    function getApproved(uint256 tokenId) external view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) external;

    function isApprovedForAll(address owner, address operator) external view returns (bool);

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

interface IERC721Metadata is IERC721 {
    function name() external view returns (string memory);

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

    function tokenURI(uint256 tokenId) external view returns (string memory);
}


// File contracts/interfaces/IOracle.sol



pragma solidity ^0.8.7;

/// @title IOracle
/// @author Angle Core Team
/// @notice Interface for Angle's oracle contracts reading oracle rates from both UniswapV3 and Chainlink
/// from just UniswapV3 or from just Chainlink
interface IOracle {
    function read() external view returns (uint256);

    function readAll() external view returns (uint256 lowerRate, uint256 upperRate);

    function readLower() external view returns (uint256);

    function readUpper() external view returns (uint256);

    function readQuote(uint256 baseAmount) external view returns (uint256);

    function readQuoteLower(uint256 baseAmount) external view returns (uint256);

    function inBase() external view returns (uint256);
}


// File contracts/interfaces/IPerpetualManager.sol



pragma solidity ^0.8.7;




/// @title Interface of the contract managing perpetuals
/// @author Angle Core Team
/// @dev Front interface, meaning only user-facing functions
interface IPerpetualManagerFront is IERC721Metadata {
    function openPerpetual(
        address owner,
        uint256 amountBrought,
        uint256 amountCommitted,
        uint256 maxOracleRate,
        uint256 minNetMargin
    ) external returns (uint256 perpetualID);

    function closePerpetual(
        uint256 perpetualID,
        address to,
        uint256 minCashOutAmount
    ) external;

    function addToPerpetual(uint256 perpetualID, uint256 amount) external;

    function removeFromPerpetual(
        uint256 perpetualID,
        uint256 amount,
        address to
    ) external;

    function liquidatePerpetuals(uint256[] memory perpetualIDs) external;

    function forceClosePerpetuals(uint256[] memory perpetualIDs) external;

    // ========================= External View Functions =============================

    function getCashOutAmount(uint256 perpetualID, uint256 rate) external view returns (uint256, uint256);

    function isApprovedOrOwner(address spender, uint256 perpetualID) external view returns (bool);
}

/// @title Interface of the contract managing perpetuals
/// @author Angle Core Team
/// @dev This interface does not contain user facing functions, it just has functions that are
/// interacted with in other parts of the protocol
interface IPerpetualManagerFunctions is IAccessControl {
    // ================================= Governance ================================

    function deployCollateral(
        address[] memory governorList,
        address guardian,
        IFeeManager feeManager,
        IOracle oracle_
    ) external;

    function setFeeManager(IFeeManager feeManager_) external;

    function setHAFees(
        uint64[] memory _xHAFees,
        uint64[] memory _yHAFees,
        uint8 deposit
    ) external;

    function setTargetAndLimitHAHedge(uint64 _targetHAHedge, uint64 _limitHAHedge) external;

    function setKeeperFeesLiquidationRatio(uint64 _keeperFeesLiquidationRatio) external;

    function setKeeperFeesCap(uint256 _keeperFeesLiquidationCap, uint256 _keeperFeesClosingCap) external;

    function setKeeperFeesClosing(uint64[] memory _xKeeperFeesClosing, uint64[] memory _yKeeperFeesClosing) external;

    function setLockTime(uint64 _lockTime) external;

    function setBoundsPerpetual(uint64 _maxLeverage, uint64 _maintenanceMargin) external;

    function pause() external;

    function unpause() external;

    // ==================================== Keepers ================================

    function setFeeKeeper(uint64 feeDeposit, uint64 feesWithdraw) external;

    // =============================== StableMaster ================================

    function setOracle(IOracle _oracle) external;
}

/// @title IPerpetualManager
/// @author Angle Core Team
/// @notice Previous interface with additionnal getters for public variables
interface IPerpetualManager is IPerpetualManagerFunctions {
    function poolManager() external view returns (address);

    function oracle() external view returns (address);

    function targetHAHedge() external view returns (uint64);

    function totalHedgeAmount() external view returns (uint256);
}


// File contracts/interfaces/IPoolManager.sol



pragma solidity ^0.8.7;



// Struct for the parameters associated to a strategy interacting with a collateral `PoolManager`
// contract
struct StrategyParams {
    // Timestamp of last report made by this strategy
    // It is also used to check if a strategy has been initialized
    uint256 lastReport;
    // Total amount the strategy is expected to have
    uint256 totalStrategyDebt;
    // The share of the total assets in the `PoolManager` contract that the `strategy` can access to.
    uint256 debtRatio;
}

/// @title IPoolManagerFunctions
/// @author Angle Core Team
/// @notice Interface for the collateral poolManager contracts handling each one type of collateral for
/// a given stablecoin
/// @dev Only the functions used in other contracts of the protocol are left here
interface IPoolManagerFunctions {
    // ============================ Constructor ====================================

    function deployCollateral(
        address[] memory governorList,
        address guardian,
        IPerpetualManager _perpetualManager,
        IFeeManager feeManager,
        IOracle oracle
    ) external;

    // ============================ Yield Farming ==================================

    function creditAvailable() external view returns (uint256);

    function debtOutstanding() external view returns (uint256);

    function report(
        uint256 _gain,
        uint256 _loss,
        uint256 _debtPayment
    ) external;

    // ============================ Governance =====================================

    function addGovernor(address _governor) external;

    function removeGovernor(address _governor) external;

    function setGuardian(address _guardian, address guardian) external;

    function revokeGuardian(address guardian) external;

    function setFeeManager(IFeeManager _feeManager) external;

    // ============================= Getters =======================================

    function getBalance() external view returns (uint256);

    function getTotalAsset() external view returns (uint256);
}

/// @title IPoolManager
/// @author Angle Core Team
/// @notice Previous interface with additionnal getters for public variables and mappings
/// @dev Used in other contracts of the protocol
interface IPoolManager is IPoolManagerFunctions {
    function stableMaster() external view returns (address);

    function perpetualManager() external view returns (address);

    function token() external view returns (address);

    function feeManager() external view returns (address);

    function totalDebt() external view returns (uint256);

    function strategies(address _strategy) external view returns (StrategyParams memory);
}


// File contracts/interfaces/IStakingRewards.sol



pragma solidity ^0.8.7;

/// @title IStakingRewardsFunctions
/// @author Angle Core Team
/// @notice Interface for the staking rewards contract that interact with the `RewardsDistributor` contract
interface IStakingRewardsFunctions {
    function notifyRewardAmount(uint256 reward) external;

    function recoverERC20(
        address tokenAddress,
        address to,
        uint256 tokenAmount
    ) external;

    function setNewRewardsDistribution(address newRewardsDistribution) external;
}

/// @title IStakingRewards
/// @author Angle Core Team
/// @notice Previous interface with additionnal getters for public variables
interface IStakingRewards is IStakingRewardsFunctions {
    function rewardToken() external view returns (IERC20);
}


// File contracts/interfaces/IRewardsDistributor.sol



pragma solidity ^0.8.7;

/// @title IRewardsDistributor
/// @author Angle Core Team, inspired from Fei protocol
/// (https://github.com/fei-protocol/fei-protocol-core/blob/master/contracts/staking/IRewardsDistributor.sol)
/// @notice Rewards Distributor interface
interface IRewardsDistributor {
    // ========================= Public Parameter Getter ===========================

    function rewardToken() external view returns (IERC20);

    // ======================== External User Available Function ===================

    function drip(IStakingRewards stakingContract) external returns (uint256);

    // ========================= Governor Functions ================================

    function governorWithdrawRewardToken(uint256 amount, address governance) external;

    function governorRecover(
        address tokenAddress,
        address to,
        uint256 amount,
        IStakingRewards stakingContract
    ) external;

    function setUpdateFrequency(uint256 _frequency, IStakingRewards stakingContract) external;

    function setIncentiveAmount(uint256 _incentiveAmount, IStakingRewards stakingContract) external;

    function setAmountToDistribute(uint256 _amountToDistribute, IStakingRewards stakingContract) external;

    function setDuration(uint256 _duration, IStakingRewards stakingContract) external;

    function setStakingContract(
        address _stakingContract,
        uint256 _duration,
        uint256 _incentiveAmount,
        uint256 _dripFrequency,
        uint256 _amountToDistribute
    ) external;

    function setNewRewardsDistributor(address newRewardsDistributor) external;

    function removeStakingContract(IStakingRewards stakingContract) external;
}


// File @openzeppelin/contracts-upgradeable/token/ERC20/[email protected]



pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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


// File contracts/interfaces/ISanToken.sol



pragma solidity ^0.8.7;

/// @title ISanToken
/// @author Angle Core Team
/// @notice Interface for Angle's `SanToken` contract that handles sanTokens, tokens that are given to SLPs
/// contributing to a collateral for a given stablecoin
interface ISanToken is IERC20Upgradeable {
    // ================================== StableMaster =============================

    function mint(address account, uint256 amount) external;

    function burnFrom(
        uint256 amount,
        address burner,
        address sender
    ) external;

    function burnSelf(uint256 amount, address burner) external;

    function stableMaster() external view returns (address);

    function poolManager() external view returns (address);
}


// File contracts/interfaces/IStableMaster.sol



pragma solidity ^0.8.7;

// Normally just importing `IPoolManager` should be sufficient, but for clarity here
// we prefer to import all concerned interfaces




// Struct to handle all the parameters to manage the fees
// related to a given collateral pool (associated to the stablecoin)
struct MintBurnData {
    // Values of the thresholds to compute the minting fees
    // depending on HA hedge (scaled by `BASE_PARAMS`)
    uint64[] xFeeMint;
    // Values of the fees at thresholds (scaled by `BASE_PARAMS`)
    uint64[] yFeeMint;
    // Values of the thresholds to compute the burning fees
    // depending on HA hedge (scaled by `BASE_PARAMS`)
    uint64[] xFeeBurn;
    // Values of the fees at thresholds (scaled by `BASE_PARAMS`)
    uint64[] yFeeBurn;
    // Max proportion of collateral from users that can be covered by HAs
    // It is exactly the same as the parameter of the same name in `PerpetualManager`, whenever one is updated
    // the other changes accordingly
    uint64 targetHAHedge;
    // Minting fees correction set by the `FeeManager` contract: they are going to be multiplied
    // to the value of the fees computed using the hedge curve
    // Scaled by `BASE_PARAMS`
    uint64 bonusMalusMint;
    // Burning fees correction set by the `FeeManager` contract: they are going to be multiplied
    // to the value of the fees computed using the hedge curve
    // Scaled by `BASE_PARAMS`
    uint64 bonusMalusBurn;
    // Parameter used to limit the number of stablecoins that can be issued using the concerned collateral
    uint256 capOnStableMinted;
}

// Struct to handle all the variables and parameters to handle SLPs in the protocol
// including the fraction of interests they receive or the fees to be distributed to
// them
struct SLPData {
    // Last timestamp at which the `sanRate` has been updated for SLPs
    uint256 lastBlockUpdated;
    // Fees accumulated from previous blocks and to be distributed to SLPs
    uint256 lockedInterests;
    // Max interests used to update the `sanRate` in a single block
    // Should be in collateral token base
    uint256 maxInterestsDistributed;
    // Amount of fees left aside for SLPs and that will be distributed
    // when the protocol is collateralized back again
    uint256 feesAside;
    // Part of the fees normally going to SLPs that is left aside
    // before the protocol is collateralized back again (depends on collateral ratio)
    // Updated by keepers and scaled by `BASE_PARAMS`
    uint64 slippageFee;
    // Portion of the fees from users minting and burning
    // that goes to SLPs (the rest goes to surplus)
    uint64 feesForSLPs;
    // Slippage factor that's applied to SLPs exiting (depends on collateral ratio)
    // If `slippage = BASE_PARAMS`, SLPs can get nothing, if `slippage = 0` they get their full claim
    // Updated by keepers and scaled by `BASE_PARAMS`
    uint64 slippage;
    // Portion of the interests from lending
    // that goes to SLPs (the rest goes to surplus)
    uint64 interestsForSLPs;
}

/// @title IStableMasterFunctions
/// @author Angle Core Team
/// @notice Interface for the `StableMaster` contract
interface IStableMasterFunctions {
    function deploy(
        address[] memory _governorList,
        address _guardian,
        address _agToken
    ) external;

    // ============================== Lending ======================================

    function accumulateInterest(uint256 gain) external;

    function signalLoss(uint256 loss) external;

    // ============================== HAs ==========================================

    function getStocksUsers() external view returns (uint256 maxCAmountInStable);

    function convertToSLP(uint256 amount, address user) external;

    // ============================== Keepers ======================================

    function getCollateralRatio() external returns (uint256);

    function setFeeKeeper(
        uint64 feeMint,
        uint64 feeBurn,
        uint64 _slippage,
        uint64 _slippageFee
    ) external;

    // ============================== AgToken ======================================

    function updateStocksUsers(uint256 amount, address poolManager) external;

    // ============================= Governance ====================================

    function setCore(address newCore) external;

    function addGovernor(address _governor) external;

    function removeGovernor(address _governor) external;

    function setGuardian(address newGuardian, address oldGuardian) external;

    function revokeGuardian(address oldGuardian) external;

    function setCapOnStableAndMaxInterests(
        uint256 _capOnStableMinted,
        uint256 _maxInterestsDistributed,
        IPoolManager poolManager
    ) external;

    function setIncentivesForSLPs(
        uint64 _feesForSLPs,
        uint64 _interestsForSLPs,
        IPoolManager poolManager
    ) external;

    function setUserFees(
        IPoolManager poolManager,
        uint64[] memory _xFee,
        uint64[] memory _yFee,
        uint8 _mint
    ) external;

    function setTargetHAHedge(uint64 _targetHAHedge) external;

    function pause(bytes32 agent, IPoolManager poolManager) external;

    function unpause(bytes32 agent, IPoolManager poolManager) external;
}

/// @title IStableMaster
/// @author Angle Core Team
/// @notice Previous interface with additionnal getters for public variables and mappings
interface IStableMaster is IStableMasterFunctions {
    function agToken() external view returns (address);

    function collateralMap(IPoolManager poolManager)
        external
        view
        returns (
            IERC20 token,
            ISanToken sanToken,
            IPerpetualManager perpetualManager,
            IOracle oracle,
            uint256 stocksUsers,
            uint256 sanRate,
            uint256 collatBase,
            SLPData memory slpData,
            MintBurnData memory feeData
        );
}


// File contracts/utils/FunctionUtils.sol



pragma solidity ^0.8.7;

/// @title FunctionUtils
/// @author Angle Core Team
/// @notice Contains all the utility functions that are needed in different places of the protocol
/// @dev Functions in this contract should typically be pure functions
/// @dev This contract is voluntarily a contract and not a library to save some gas cost every time it is used
contract FunctionUtils {
    /// @notice Base that is used to compute ratios and floating numbers
    uint256 public constant BASE_TOKENS = 10**18;
    /// @notice Base that is used to define parameters that need to have a floating value (for instance parameters
    /// that are defined as ratios)
    uint256 public constant BASE_PARAMS = 10**9;

    /// @notice Computes the value of a linear by part function at a given point
    /// @param x Point of the function we want to compute
    /// @param xArray List of breaking points (in ascending order) that define the linear by part function
    /// @param yArray List of values at breaking points (not necessarily in ascending order)
    /// @dev The evolution of the linear by part function between two breaking points is linear
    /// @dev Before the first breaking point and after the last one, the function is constant with a value
    /// equal to the first or last value of the yArray
    /// @dev This function is relevant if `x` is between O and `BASE_PARAMS`. If `x` is greater than that, then
    /// everything will be as if `x` is equal to the greater element of the `xArray`
    function _piecewiseLinear(
        uint64 x,
        uint64[] memory xArray,
        uint64[] memory yArray
    ) internal pure returns (uint64) {
        if (x >= xArray[xArray.length - 1]) {
            return yArray[xArray.length - 1];
        } else if (x <= xArray[0]) {
            return yArray[0];
        } else {
            uint256 lower;
            uint256 upper = xArray.length - 1;
            uint256 mid;
            while (upper - lower > 1) {
                mid = lower + (upper - lower) / 2;
                if (xArray[mid] <= x) {
                    lower = mid;
                } else {
                    upper = mid;
                }
            }
            if (yArray[upper] > yArray[lower]) {
                // There is no risk of overflow here as in the product of the difference of `y`
                // with the difference of `x`, the product is inferior to `BASE_PARAMS**2` which does not
                // overflow for `uint64`
                return
                    yArray[lower] +
                    ((yArray[upper] - yArray[lower]) * (x - xArray[lower])) /
                    (xArray[upper] - xArray[lower]);
            } else {
                return
                    yArray[lower] -
                    ((yArray[lower] - yArray[upper]) * (x - xArray[lower])) /
                    (xArray[upper] - xArray[lower]);
            }
        }
    }

    /// @notice Checks if the input arrays given by governance to update the fee structure is valid
    /// @param xArray List of breaking points (in ascending order) that define the linear by part function
    /// @param yArray List of values at breaking points (not necessarily in ascending order)
    /// @dev This function is a way to avoid some governance attacks or errors
    /// @dev The modifier checks if the arrays have a non null length, if their length is the same, if the values
    /// in the `xArray` are in ascending order and if the values in the `xArray` and in the `yArray` are not superior
    /// to `BASE_PARAMS`
    modifier onlyCompatibleInputArrays(uint64[] memory xArray, uint64[] memory yArray) {
        require(xArray.length == yArray.length && xArray.length > 0, "5");
        for (uint256 i = 0; i <= yArray.length - 1; i++) {
            require(yArray[i] <= uint64(BASE_PARAMS) && xArray[i] <= uint64(BASE_PARAMS), "6");
            if (i > 0) {
                require(xArray[i] > xArray[i - 1], "7");
            }
        }
        _;
    }

    /// @notice Checks if the new value given for the parameter is consistent (it should be inferior to 1
    /// if it corresponds to a ratio)
    /// @param fees Value of the new parameter to check
    modifier onlyCompatibleFees(uint64 fees) {
        require(fees <= BASE_PARAMS, "4");
        _;
    }

    /// @notice Checks if the new address given is not null
    /// @param newAddress Address to check
    /// @dev Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation
    modifier zeroCheck(address newAddress) {
        require(newAddress != address(0), "0");
        _;
    }
}


// File contracts/perpetualManager/PerpetualManagerEvents.sol



pragma solidity ^0.8.7;















// Used in the `forceCashOutPerpetuals` function to store owners of perpetuals which have been force cashed
// out, along with the amount associated to it
struct Pairs {
    address owner;
    uint256 netCashOutAmount;
}

/// @title PerpetualManagerEvents
/// @author Angle Core Team
/// @notice `PerpetualManager` is the contract handling all the Hedging Agents perpetuals
/// @dev There is one `PerpetualManager` contract per pair stablecoin/collateral in the protocol
/// @dev This file contains all the events of the `PerpetualManager` contract
contract PerpetualManagerEvents {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event PerpetualUpdated(uint256 _perpetualID, uint256 _margin);

    event PerpetualOpened(uint256 _perpetualID, uint256 _entryRate, uint256 _margin, uint256 _committedAmount);

    event PerpetualClosed(uint256 _perpetualID, uint256 _closeAmount);

    event PerpetualsForceClosed(uint256[] perpetualIDs, Pairs[] ownerAndCashOut, address keeper, uint256 reward);

    event KeeperTransferred(address keeperAddress, uint256 liquidationFees);

    // ============================== Parameters ===================================

    event BaseURIUpdated(string _baseURI);

    event LockTimeUpdated(uint64 _lockTime);

    event KeeperFeesCapUpdated(uint256 _keeperFeesLiquidationCap, uint256 _keeperFeesClosingCap);

    event TargetAndLimitHAHedgeUpdated(uint64 _targetHAHedge, uint64 _limitHAHedge);

    event BoundsPerpetualUpdated(uint64 _maxLeverage, uint64 _maintenanceMargin);

    event HAFeesUpdated(uint64[] _xHAFees, uint64[] _yHAFees, uint8 deposit);

    event KeeperFeesLiquidationRatioUpdated(uint64 _keeperFeesLiquidationRatio);

    event KeeperFeesClosingUpdated(uint64[] xKeeperFeesClosing, uint64[] yKeeperFeesClosing);

    // =============================== Reward ======================================

    event RewardAdded(uint256 _reward);

    event RewardPaid(address indexed _user, uint256 _reward);

    event RewardsDistributionUpdated(address indexed _rewardsDistributor);

    event RewardsDistributionDurationUpdated(uint256 _rewardsDuration, address indexed _rewardsDistributor);

    event Recovered(address indexed tokenAddress, address indexed to, uint256 amount);
}


// File contracts/perpetualManager/PerpetualManagerStorage.sol



pragma solidity ^0.8.7;

struct Perpetual {
    // Oracle value at the moment of perpetual opening
    uint256 entryRate;
    // Timestamp at which the perpetual was opened
    uint256 entryTimestamp;
    // Amount initially brought in the perpetual (net from fees) + amount added - amount removed from it
    // This is the only element that can be modified in the perpetual after its creation
    uint256 margin;
    // Amount of collateral covered by the perpetual. This cannot be modified once the perpetual is opened.
    // The amount covered is used interchangeably with the amount hedged
    uint256 committedAmount;
}

/// @title PerpetualManagerStorage
/// @author Angle Core Team
/// @notice `PerpetualManager` is the contract handling all the Hedging Agents positions and perpetuals
/// @dev There is one `PerpetualManager` contract per pair stablecoin/collateral in the protocol
/// @dev This file contains all the parameters and references used in the `PerpetualManager` contract
// solhint-disable-next-line max-states-count
contract PerpetualManagerStorage is PerpetualManagerEvents, FunctionUtils {
    // Base used in the collateral implementation (ERC20 decimal)
    uint256 internal _collatBase;

    // ============================== Perpetual Variables ==========================

    /// @notice Total amount of stablecoins that are insured (i.e. that could be redeemed against
    /// collateral thanks to HAs)
    /// When a HA opens a perpetual, it covers/hedges a fixed amount of stablecoins for the protocol, equal to
    /// the committed amount times the entry rate
    /// `totalHedgeAmount` is the sum of all these hedged amounts
    uint256 public totalHedgeAmount;

    // Counter to generate a unique `perpetualID` for each perpetual
    CountersUpgradeable.Counter internal _perpetualIDcount;

    // ========================== Mutable References ============================

    /// @notice `Oracle` to give the rate feed, that is the price of the collateral
    /// with respect to the price of the stablecoin
    /// This reference can be modified by the corresponding `StableMaster` contract
    IOracle public oracle;

    // `FeeManager` address allowed to update the way fees are computed for this contract
    // This reference can be modified by the `PoolManager` contract
    IFeeManager internal _feeManager;

    // ========================== Immutable References ==========================

    /// @notice Interface for the `rewardToken` distributed as a reward
    /// As of Angle V1, only a single `rewardToken` can be distributed to HAs who own a perpetual
    /// This implementation assumes that reward tokens have a base of 18 decimals
    IERC20 public rewardToken;

    /// @notice Address of the `PoolManager` instance
    IPoolManager public poolManager;

    // Address of the `StableMaster` instance
    IStableMaster internal _stableMaster;

    // Interface for the underlying token accepted by this contract
    // This reference cannot be changed, it is taken from the `PoolManager`
    IERC20 internal _token;

    // ======================= Fees and other Parameters ===========================

    /// Deposit fees for HAs depend on the hedge ratio that is the ratio between what is hedged
    /// (or covered, this is a synonym) by HAs compared with the total amount to hedge
    /// @notice Thresholds for the ratio between to amount hedged and the amount to hedge
    /// The bigger the ratio the bigger the fees will be because this means that the max amount
    /// to insure is soon to be reached
    uint64[] public xHAFeesDeposit;

    /// @notice Deposit fees at threshold values
    /// This array should have the same length as the array above
    /// The evolution of the fees between two threshold values is linear
    uint64[] public yHAFeesDeposit;

    /// Withdraw fees for HAs also depend on the hedge ratio
    /// @notice Thresholds for the hedge ratio
    uint64[] public xHAFeesWithdraw;

    /// @notice Withdraw fees at threshold values
    uint64[] public yHAFeesWithdraw;

    /// @notice Maintenance Margin (in `BASE_PARAMS`) for each perpetual
    /// The margin ratio is defined for a perpetual as: `(initMargin + PnL) / committedAmount` where
    /// `PnL = committedAmount * (1 - initRate/currentRate)`
    /// If the `marginRatio` is below `maintenanceMargin`: then the perpetual can be liquidated
    uint64 public maintenanceMargin;

    /// @notice Maximum leverage multiplier authorized for HAs (`in BASE_PARAMS`)
    /// Leverage for a perpetual here corresponds to the ratio between the amount committed
    /// and the margin of the perpetual
    uint64 public maxLeverage;

    /// @notice Target proportion of stablecoins issued using this collateral to insure with HAs.
    /// This variable is exactly the same as the one in the `StableMaster` contract for this collateral.
    /// Above this hedge ratio, HAs cannot open new perpetuals
    /// When keepers are forcing the closing of some perpetuals, they are incentivized to bringing
    /// the hedge ratio to this proportion
    uint64 public targetHAHedge;

    /// @notice Limit proportion of stablecoins issued using this collateral that HAs can insure
    /// Above this ratio `forceCashOut` is activated and anyone can see its perpetual cashed out
    uint64 public limitHAHedge;

    /// @notice Extra parameter from the `FeeManager` contract that is multiplied to the fees from above and that
    /// can be used to change deposit fees. It works as a bonus - malus fee, if `haBonusMalusDeposit > BASE_PARAMS`,
    /// then the fee will be larger than `haFeesDeposit`, if `haBonusMalusDeposit < BASE_PARAMS`, fees will be smaller.
    /// This parameter, updated by keepers in the `FeeManager` contract, could most likely depend on the collateral ratio
    uint64 public haBonusMalusDeposit;

    /// @notice Extra parameter from the `FeeManager` contract that is multiplied to the fees from above and that
    /// can be used to change withdraw fees. It works as a bonus - malus fee, if `haBonusMalusWithdraw > BASE_PARAMS`,
    /// then the fee will be larger than `haFeesWithdraw`, if `haBonusMalusWithdraw < BASE_PARAMS`, fees will be smaller
    uint64 public haBonusMalusWithdraw;

    /// @notice Amount of time before HAs are allowed to withdraw funds from their perpetuals
    /// either using `removeFromPerpetual` or `closePerpetual`. New perpetuals cannot be forced closed in
    /// situations where the `forceClosePerpetuals` function is activated before this `lockTime` elapsed
    uint64 public lockTime;

    // ================================= Keeper fees ======================================
    // All these parameters can be modified by their corresponding governance function

    /// @notice Portion of the leftover cash out amount of liquidated perpetuals that go to
    /// liquidating keepers
    uint64 public keeperFeesLiquidationRatio;

    /// @notice Cap on the fees that go to keepers liquidating a perpetual
    /// If a keeper liquidates n perpetuals in a single transaction, then this keeper is entitled to get as much as
    /// `n * keeperFeesLiquidationCap` as a reward
    uint256 public keeperFeesLiquidationCap;

    /// @notice Cap on the fees that go to keepers closing perpetuals when too much collateral is hedged by HAs
    /// (hedge ratio above `limitHAHedge`)
    /// If a keeper forces the closing of n perpetuals in a single transaction, then this keeper is entitled to get
    /// as much as `keeperFeesClosingCap`. This cap amount is independent of the number of perpetuals closed
    uint256 public keeperFeesClosingCap;

    /// @notice Thresholds on the values of the rate between the current hedged amount (`totalHedgeAmount`) and the
    /// target hedged amount by HAs (`targetHedgeAmount`) divided by 2. A value of `0.5` corresponds to a hedge ratio
    /// of `1`. Doing this allows to maintain an array with values of `x` inferior to `BASE_PARAMS`.
    uint64[] public xKeeperFeesClosing;

    /// @notice Values at thresholds of the proportions of the fees that should go to keepers closing perpetuals
    uint64[] public yKeeperFeesClosing;

    // =========================== Staking Parameters ==============================

    /// @notice Below are parameters that can also be found in other staking contracts
    /// to be able to compute rewards from staking (having perpetuals here) correctly
    uint256 public periodFinish;
    uint256 public rewardRate;
    uint256 public rewardsDuration;
    uint256 public lastUpdateTime;
    uint256 public rewardPerTokenStored;
    address public rewardsDistribution;

    // ============================== ERC721 Base URI ==============================

    /// @notice URI used for the metadata of the perpetuals
    string public baseURI;

    // =============================== Mappings ====================================

    /// @notice Mapping from `perpetualID` to perpetual data
    mapping(uint256 => Perpetual) public perpetualData;

    /// @notice Mapping used to compute the rewards earned by a perpetual in a timeframe
    mapping(uint256 => uint256) public perpetualRewardPerTokenPaid;

    /// @notice Mapping used to get how much rewards in governance tokens are gained by a perpetual
    // identified by its ID
    mapping(uint256 => uint256) public rewards;

    // Mapping from `perpetualID` to owner address
    mapping(uint256 => address) internal _owners;

    // Mapping from owner address to perpetual owned count
    mapping(address => uint256) internal _balances;

    // Mapping from `perpetualID` to approved address
    mapping(uint256 => address) internal _perpetualApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) internal _operatorApprovals;
}


// File contracts/perpetualManager/PerpetualManagerInternal.sol



pragma solidity ^0.8.7;

/// @title PerpetualManagerInternal
/// @author Angle Core Team
/// @notice `PerpetualManager` is the contract handling all the Hedging Agents perpetuals
/// @dev There is one `PerpetualManager` contract per pair stablecoin/collateral in the protocol
/// @dev This file contains all the internal functions of the `PerpetualManager` contract
contract PerpetualManagerInternal is PerpetualManagerStorage {
    using Address for address;
    using SafeERC20 for IERC20;

    // ======================== State Modifying Functions ==========================

    /// @notice Cashes out a perpetual, which means that it simply deletes the references to the perpetual
    /// in the contract
    /// @param perpetualID ID of the perpetual
    /// @param perpetual Data of the perpetual
    function _closePerpetual(uint256 perpetualID, Perpetual memory perpetual) internal {
        // Handling the staking logic
        // Reward should always be updated before the `totalHedgeAmount`
        // Rewards are distributed to the perpetual which is liquidated
        uint256 hedge = perpetual.committedAmount * perpetual.entryRate;
        _getReward(perpetualID, hedge);
        delete perpetualRewardPerTokenPaid[perpetualID];

        // Updating `totalHedgeAmount` to represent the fact that less money is insured
        totalHedgeAmount -= hedge / _collatBase;

        _burn(perpetualID);
    }

    /// @notice Allows the protocol to transfer collateral to an address while handling the case where there are
    /// not enough reserves
    /// @param owner Address of the receiver
    /// @param amount The amount of collateral sent
    /// @dev If there is not enough collateral in balance (this can happen when money has been lent to strategies),
    /// then the owner is reimbursed by receiving what is missing in sanTokens at the correct value
    function _secureTransfer(address owner, uint256 amount) internal {
        uint256 curBalance = poolManager.getBalance();
        if (curBalance >= amount && amount > 0) {
            // Case where there is enough in reserves to reimburse the person
            _token.safeTransferFrom(address(poolManager), owner, amount);
        } else if (amount > 0) {
            // When there is not enough to reimburse the entire amount, the protocol reimburses
            // what it can using its reserves and the rest is paid in sanTokens at the current
            // exchange rate
            uint256 amountLeft = amount - curBalance;
            _token.safeTransferFrom(address(poolManager), owner, curBalance);
            _stableMaster.convertToSLP(amountLeft, owner);
        }
    }

    /// @notice Checks whether the perpetual should be liquidated or not, and if so liquidates the perpetual
    /// @param perpetualID ID of the perpetual to check and potentially liquidate
    /// @param perpetual Data of the perpetual to check
    /// @param rateDown Oracle value to compute the cash out amount of the perpetual
    /// @return Cash out amount of the perpetual
    /// @return Whether the perpetual was liquidated or not
    /// @dev Generally, to check for the liquidation of a perpetual, we use the lowest oracle value possible:
    /// it's the one that is most at the advantage of the protocol, hence the `rateDown` parameter
    function _checkLiquidation(
        uint256 perpetualID,
        Perpetual memory perpetual,
        uint256 rateDown
    ) internal returns (uint256, uint256) {
        uint256 liquidated;
        (uint256 cashOutAmount, uint256 reachMaintenanceMargin) = _getCashOutAmount(perpetual, rateDown);
        if (cashOutAmount == 0 || reachMaintenanceMargin == 1) {
            _closePerpetual(perpetualID, perpetual);
            // No need for an event to find out that a perpetual is liquidated
            liquidated = 1;
        }
        return (cashOutAmount, liquidated);
    }

    // ========================= Internal View Functions ===========================

    /// @notice Gets the current cash out amount of a perpetual
    /// @param perpetual Data of the concerned perpetual
    /// @param rate Value of the oracle
    /// @return cashOutAmount Amount that the HA could get by closing this perpetual
    /// @return reachMaintenanceMargin Whether the position of the perpetual is now too small
    /// compared with its initial position
    /// @dev Refer to the whitepaper or the doc for the formulas of the cash out amount
    /// @dev The notion of `maintenanceMargin` is standard in centralized platforms offering perpetual futures
    function _getCashOutAmount(Perpetual memory perpetual, uint256 rate)
        internal
        view
        returns (uint256 cashOutAmount, uint256 reachMaintenanceMargin)
    {
        // All these computations are made just because we are working with uint and not int
        // so we cannot do x-y if x<y
        uint256 newCommit = (perpetual.committedAmount * perpetual.entryRate) / rate;
        // Checking if a liquidation is needed: for this to happen the `cashOutAmount` should be inferior
        // to the maintenance margin of the perpetual
        reachMaintenanceMargin;
        if (newCommit >= perpetual.committedAmount + perpetual.margin) cashOutAmount = 0;
        else {
            // The definition of the margin ratio is `(margin + PnL) / committedAmount`
            // where `PnL = commit * (1-entryRate/currentRate)`
            // So here: `newCashOutAmount = margin + PnL`
            cashOutAmount = perpetual.committedAmount + perpetual.margin - newCommit;
            if (cashOutAmount * BASE_PARAMS <= perpetual.committedAmount * maintenanceMargin)
                reachMaintenanceMargin = 1;
        }
    }

    /// @notice Calls the oracle to read both Chainlink and Uniswap rates
    /// @return The lowest oracle value (between Chainlink and Uniswap) is the first outputted value
    /// @return The highest oracle value is the second output
    /// @dev If the oracle only involves a single oracle fees (like just Chainlink for USD-EUR),
    /// the same value is returned twice
    function _getOraclePrice() internal view returns (uint256, uint256) {
        return oracle.readAll();
    }

    /// @notice Computes the incentive for the keeper as a function of the cash out amount of a liquidated perpetual
    /// which value falls below its maintenance margin
    /// @param cashOutAmount Value remaining in the perpetual
    /// @dev By computing keeper fees as a fraction of the cash out amount of a perpetual rather than as a fraction
    /// of the `committedAmount`, keepers are incentivized to react fast when a perpetual is below the maintenance margin
    /// @dev Perpetual exchange protocols typically compute liquidation fees using an equivalent of the `committedAmount`,
    /// this is not the case here
    function _computeKeeperLiquidationFees(uint256 cashOutAmount) internal view returns (uint256 keeperFees) {
        keeperFees = (cashOutAmount * keeperFeesLiquidationRatio) / BASE_PARAMS;
        keeperFees = keeperFees < keeperFeesLiquidationCap ? keeperFees : keeperFeesLiquidationCap;
    }

    /// @notice Gets the value of the hedge ratio that is the ratio between the amount currently hedged by HAs
    /// and the target amount that should be hedged by them
    /// @param currentHedgeAmount Amount currently covered by HAs
    /// @return ratio Ratio between the amount of collateral (in stablecoin value) currently hedged
    /// and the target amount to hedge
    function _computeHedgeRatio(uint256 currentHedgeAmount) internal view returns (uint64 ratio) {
        // Fetching info from the `StableMaster`: the amount to hedge is based on the `stocksUsers`
        // of the given collateral
        uint256 targetHedgeAmount = (_stableMaster.getStocksUsers() * targetHAHedge) / BASE_PARAMS;
        if (currentHedgeAmount < targetHedgeAmount)
            ratio = uint64((currentHedgeAmount * BASE_PARAMS) / targetHedgeAmount);
        else ratio = uint64(BASE_PARAMS);
    }

    // =========================== Fee Computation =================================

    /// @notice Gets the net margin corrected from the fees at perpetual opening
    /// @param margin Amount brought in the perpetual at creation
    /// @param totalHedgeAmountUpdate Amount of stablecoins that this perpetual is going to insure
    /// @param committedAmount Committed amount in the perpetual, we need it to compute the fees
    /// paid by the HA
    /// @return netMargin Amount that will be written in the perpetual as the `margin`
    /// @dev The amount of stablecoins insured by a perpetual is `committedAmount * oracleRate / _collatBase`
    function _getNetMargin(
        uint256 margin,
        uint256 totalHedgeAmountUpdate,
        uint256 committedAmount
    ) internal view returns (uint256 netMargin) {
        // Checking if the HA has the right to open a perpetual with such amount
        // If HAs hedge more than the target amount, then new HAs will not be able to create perpetuals
        // The amount hedged by HAs after opening the perpetual is going to be:
        uint64 ratio = _computeHedgeRatio(totalHedgeAmount + totalHedgeAmountUpdate);
        require(ratio < uint64(BASE_PARAMS), "25");
        // Computing the net margin of HAs to store in the perpetual: it consists simply in deducing fees
        // Those depend on how much is already hedged by HAs compared with what's to hedge
        uint256 haFeesDeposit = (haBonusMalusDeposit * _piecewiseLinear(ratio, xHAFeesDeposit, yHAFeesDeposit)) /
            BASE_PARAMS;
        // Fees are rounded to the advantage of the protocol
        haFeesDeposit = committedAmount - (committedAmount * (BASE_PARAMS - haFeesDeposit)) / BASE_PARAMS;
        // Fees are computed based on the committed amount of the perpetual
        // The following reverts if fees are too big compared to the margin
        netMargin = margin - haFeesDeposit;
    }

    /// @notice Gets the net amount to give to a HA (corrected from the fees) in case of a perpetual closing
    /// @param committedAmount Committed amount in the perpetual
    /// @param cashOutAmount The current cash out amount of the perpetual
    /// @param ratio What's hedged divided by what's to hedge
    /// @return netCashOutAmount Amount that will be distributed to the HA
    /// @return feesPaid Amount of fees paid by the HA at perpetual closing
    /// @dev This function is called by the `closePerpetual` and by the `forceClosePerpetuals`
    /// function
    /// @dev The amount of fees paid by the HA is used to compute the incentive given to HAs closing perpetuals
    /// when too much is covered
    function _getNetCashOutAmount(
        uint256 cashOutAmount,
        uint256 committedAmount,
        uint64 ratio
    ) internal view returns (uint256 netCashOutAmount, uint256 feesPaid) {
        feesPaid = (haBonusMalusWithdraw * _piecewiseLinear(ratio, xHAFeesWithdraw, yHAFeesWithdraw)) / BASE_PARAMS;
        // Rounding the fees at the protocol's advantage
        feesPaid = committedAmount - (committedAmount * (BASE_PARAMS - feesPaid)) / BASE_PARAMS;
        if (feesPaid >= cashOutAmount) {
            netCashOutAmount = 0;
            feesPaid = cashOutAmount;
        } else {
            netCashOutAmount = cashOutAmount - feesPaid;
        }
    }

    // ========================= Reward Distribution ===============================

    /// @notice View function to query the last timestamp at which a reward was distributed
    /// @return Current timestamp if a reward is being distributed or the last timestamp
    function _lastTimeRewardApplicable() internal view returns (uint256) {
        uint256 returnValue = block.timestamp < periodFinish ? block.timestamp : periodFinish;
        return returnValue;
    }

    /// @notice Used to actualize the `rewardPerTokenStored`
    /// @dev It adds to the reward per token: the time elapsed since the `rewardPerTokenStored`
    /// was last updated multiplied by the `rewardRate` divided by the number of tokens
    /// @dev Specific attention should be placed on the base here: `rewardRate` is in the base of the reward token
    /// and `totalHedgeAmount` is in `BASE_TOKENS` here: as this function concerns an amount of reward
    /// tokens, the output of this function should be in the base of the reward token too
    function _rewardPerToken() internal view returns (uint256) {
        if (totalHedgeAmount == 0) {
            return rewardPerTokenStored;
        }
        return
            rewardPerTokenStored +
            ((_lastTimeRewardApplicable() - lastUpdateTime) * rewardRate * BASE_TOKENS) /
            totalHedgeAmount;
    }

    /// @notice Allows a perpetual owner to withdraw rewards
    /// @param perpetualID ID of the perpetual which accumulated tokens
    /// @param hedge Perpetual commit amount times the entry rate
    /// @dev Internal version of the `getReward` function
    /// @dev In case where an approved address calls to close a perpetual, rewards are still going to get distributed
    /// to the owner of the perpetual, and not necessarily to the address getting the proceeds of the perpetual
    function _getReward(uint256 perpetualID, uint256 hedge) internal {
        _updateReward(perpetualID, hedge);
        uint256 reward = rewards[perpetualID];
        if (reward > 0) {
            rewards[perpetualID] = 0;
            address owner = _owners[perpetualID];
            // Attention here, there may be reentrancy attacks because of the following call
            // to an external contract done before other things are modified. Yet since the `rewardToken`
            // is mostly going to be a trusted contract controlled by governance (namely the ANGLE token), then
            // there is no point in putting an expensive `nonReentrant` modifier in the functions in `PerpetualManagerFront`
            // that allow indirect interactions with `_updateReward`. If new `rewardTokens` are set, we could think about
            // upgrading the `PerpetualManagerFront` contract
            rewardToken.safeTransfer(owner, reward);
            emit RewardPaid(owner, reward);
        }
    }

    /// @notice Allows to check the amount of gov tokens earned by a perpetual
    /// @param perpetualID ID of the perpetual which accumulated tokens
    /// @param hedge Perpetual commit amount times the entry rate
    /// @return Amount of gov tokens earned by the perpetual
    /// @dev A specific attention should be paid to have the base here: we consider that each HA stakes an amount
    /// equal to `committedAmount * entryRate / _collatBase`, here as the `hedge` corresponds to `committedAmount * entryRate`,
    /// we just need to divide by `_collatBase`
    /// @dev HAs earn reward tokens which are in base `BASE_TOKENS`
    function _earned(uint256 perpetualID, uint256 hedge) internal view returns (uint256) {
        return
            (hedge * (_rewardPerToken() - perpetualRewardPerTokenPaid[perpetualID])) /
            BASE_TOKENS /
            _collatBase +
            rewards[perpetualID];
    }

    /// @notice Updates the amount of gov tokens earned by a perpetual
    /// @param perpetualID of the perpetual which earns tokens
    /// @param hedge Perpetual commit amount times the entry rate
    /// @dev When this function is called in the code, it has already been checked that the `perpetualID`
    /// exists
    function _updateReward(uint256 perpetualID, uint256 hedge) internal {
        rewardPerTokenStored = _rewardPerToken();
        lastUpdateTime = _lastTimeRewardApplicable();
        // No need to check if the `perpetualID` exists here, it has already been checked
        // in the code before when this internal function is called
        rewards[perpetualID] = _earned(perpetualID, hedge);
        perpetualRewardPerTokenPaid[perpetualID] = rewardPerTokenStored;
    }

    // =============================== ERC721 Logic ================================

    /// @notice Gets the owner of a perpetual
    /// @param perpetualID ID of the concerned perpetual
    /// @return owner Owner of the perpetual
    function _ownerOf(uint256 perpetualID) internal view returns (address owner) {
        owner = _owners[perpetualID];
        require(owner != address(0), "2");
    }

    /// @notice Gets the addresses approved for a perpetual
    /// @param perpetualID ID of the concerned perpetual
    /// @return Address approved for this perpetual
    function _getApproved(uint256 perpetualID) internal view returns (address) {
        return _perpetualApprovals[perpetualID];
    }

    /// @notice Safely transfers `perpetualID` token from `from` to `to`, checking first that contract recipients
    /// are aware of the ERC721 protocol to prevent tokens from being forever locked
    /// @param perpetualID ID of the concerned perpetual
    /// @param _data Additional data, it has no specified format and it is sent in call to `to`
    /// @dev This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
    /// implement alternative mechanisms to perform token transfer, such as signature-based
    /// @dev Requirements:
    ///     - `from` cannot be the zero address.
    ///     - `to` cannot be the zero address.
    ///     - `perpetualID` token must exist and be owned by `from`.
    ///     - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    function _safeTransfer(
        address from,
        address to,
        uint256 perpetualID,
        bytes memory _data
    ) internal {
        _transfer(from, to, perpetualID);
        require(_checkOnERC721Received(from, to, perpetualID, _data), "24");
    }

    /// @notice Returns whether `perpetualID` exists
    /// @dev Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}
    /// @dev Tokens start existing when they are minted (`_mint`),
    /// and stop existing when they are burned (`_burn`)
    function _exists(uint256 perpetualID) internal view returns (bool) {
        return _owners[perpetualID] != address(0);
    }

    /// @notice Returns whether `spender` is allowed to manage `perpetualID`
    /// @dev `perpetualID` must exist
    function _isApprovedOrOwner(address spender, uint256 perpetualID) internal view returns (bool) {
        // The following checks if the perpetual exists
        address owner = _ownerOf(perpetualID);
        return (spender == owner || _getApproved(perpetualID) == spender || _operatorApprovals[owner][spender]);
    }

    /// @notice Mints `perpetualID` and transfers it to `to`
    /// @dev This method is equivalent to the `_safeMint` method used in OpenZeppelin ERC721 contract
    /// @dev `perpetualID` must not exist and `to` cannot be the zero address
    /// @dev Before calling this function it is checked that the `perpetualID` does not exist as it
    /// comes from a counter that has been incremented
    /// @dev Emits a {Transfer} event
    function _mint(address to, uint256 perpetualID) internal {
        _balances[to] += 1;
        _owners[perpetualID] = to;
        emit Transfer(address(0), to, perpetualID);
        require(_checkOnERC721Received(address(0), to, perpetualID, ""), "24");
    }

    /// @notice Destroys `perpetualID`
    /// @dev `perpetualID` must exist
    /// @dev Emits a {Transfer} event
    function _burn(uint256 perpetualID) internal {
        address owner = _ownerOf(perpetualID);

        // Clear approvals
        _approve(address(0), perpetualID);

        _balances[owner] -= 1;
        delete _owners[perpetualID];
        delete perpetualData[perpetualID];

        emit Transfer(owner, address(0), perpetualID);
    }

    /// @notice Transfers `perpetualID` from `from` to `to` as opposed to {transferFrom},
    /// this imposes no restrictions on msg.sender
    /// @dev `to` cannot be the zero address and `perpetualID` must be owned by `from`
    /// @dev Emits a {Transfer} event
    function _transfer(
        address from,
        address to,
        uint256 perpetualID
    ) internal {
        require(_ownerOf(perpetualID) == from, "1");
        require(to != address(0), "26");

        // Clear approvals from the previous owner
        _approve(address(0), perpetualID);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[perpetualID] = to;

        emit Transfer(from, to, perpetualID);
    }

    /// @notice Approves `to` to operate on `perpetualID`
    function _approve(address to, uint256 perpetualID) internal {
        _perpetualApprovals[perpetualID] = to;
        emit Approval(_ownerOf(perpetualID), to, perpetualID);
    }

    /// @notice Internal function to invoke {IERC721Receiver-onERC721Received} on a target address
    /// The call is not executed if the target address is not a contract
    /// @param from Address representing the previous owner of the given token ID
    /// @param to Target address that will receive the tokens
    /// @param perpetualID ID of the token to be transferred
    /// @param _data Bytes optional data to send along with the call
    /// @return Bool whether the call correctly returned the expected magic value
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 perpetualID,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721ReceiverUpgradeable(to).onERC721Received(msg.sender, from, perpetualID, _data) returns (
                bytes4 retval
            ) {
                return retval == IERC721ReceiverUpgradeable(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("24");
                } else {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }
}


// File contracts/perpetualManager/PerpetualManager.sol



pragma solidity ^0.8.7;

/// @title PerpetualManager
/// @author Angle Core Team
/// @notice `PerpetualManager` is the contract handling all the Hedging Agents positions and perpetuals
/// @dev There is one `PerpetualManager` contract per pair stablecoin/collateral in the protocol
/// @dev This file contains the functions of the `PerpetualManager` that can be interacted with
/// by `StableMaster`, by the `PoolManager`, by the `FeeManager` and by governance
contract PerpetualManager is
    PerpetualManagerInternal,
    IPerpetualManagerFunctions,
    IStakingRewardsFunctions,
    AccessControlUpgradeable,
    PausableUpgradeable
{
    using SafeERC20 for IERC20;

    /// @notice Role for guardians, governors and `StableMaster`
    /// Made for the `StableMaster` to be able to update some parameters
    bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
    /// @notice Role for `PoolManager` only
    bytes32 public constant POOLMANAGER_ROLE = keccak256("POOLMANAGER_ROLE");

    // ============================== Modifiers ====================================

    /// @notice Checks if the person interacting with the perpetual with `perpetualID` is approved
    /// @param caller Address of the person seeking to interact with the perpetual
    /// @param perpetualID ID of the concerned perpetual
    /// @dev Generally in `PerpetualManager`, perpetual owners should store the ID of the perpetuals
    /// they are able to interact with
    modifier onlyApprovedOrOwner(address caller, uint256 perpetualID) {
        require(_isApprovedOrOwner(caller, perpetualID), "21");
        _;
    }

    /// @notice Checks if the message sender is the rewards distribution address
    modifier onlyRewardsDistribution() {
        require(msg.sender == rewardsDistribution, "1");
        _;
    }

    // =============================== Deployer ====================================

    /// @notice Notifies the address of the `_feeManager` and of the `oracle`
    /// to this contract and grants the correct roles
    /// @param governorList List of governor addresses of the protocol
    /// @param guardian Address of the guardian of the protocol
    /// @param feeManager_ Reference to the `FeeManager` contract which will be able to update fees
    /// @param oracle_ Reference to the `oracle` contract which will be able to update fees
    /// @dev Called by the `PoolManager` contract when it is activated by the `StableMaster`
    /// @dev The `governorList` and `guardian` here are those of the `Core` contract
    function deployCollateral(
        address[] memory governorList,
        address guardian,
        IFeeManager feeManager_,
        IOracle oracle_
    ) external override onlyRole(POOLMANAGER_ROLE) {
        for (uint256 i = 0; i < governorList.length; i++) {
            _grantRole(GUARDIAN_ROLE, governorList[i]);
        }
        // In the end guardian should be revoked by governance
        _grantRole(GUARDIAN_ROLE, guardian);
        _grantRole(GUARDIAN_ROLE, address(_stableMaster));
        _feeManager = feeManager_;
        oracle = oracle_;
    }

    // ========================== Rewards Distribution =============================

    /// @notice Notifies the contract that rewards are going to be shared among HAs of this pool
    /// @param reward Amount of governance tokens to be distributed to HAs
    /// @dev Only the reward distributor contract is allowed to call this function which starts a staking cycle
    /// @dev This function is the equivalent of the `notifyRewardAmount` function found in all staking contracts
    function notifyRewardAmount(uint256 reward) external override onlyRewardsDistribution {
        rewardPerTokenStored = _rewardPerToken();

        if (block.timestamp >= periodFinish) {
            // If the period is not done, then the reward rate changes
            rewardRate = reward / rewardsDuration;
        } else {
            uint256 remaining = periodFinish - block.timestamp;
            uint256 leftover = remaining * rewardRate;
            // If the period is not over, we compute the reward left and increase reward duration
            rewardRate = (reward + leftover) / rewardsDuration;
        }
        // Ensuring the provided reward amount is not more than the balance in the contract.
        // This keeps the reward rate in the right range, preventing overflows due to
        // very high values of `rewardRate` in the earned and `rewardsPerToken` functions;
        // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
        uint256 balance = rewardToken.balanceOf(address(this));

        require(rewardRate <= balance / rewardsDuration, "22");

        lastUpdateTime = block.timestamp;
        // Change the duration
        periodFinish = block.timestamp + rewardsDuration;
        emit RewardAdded(reward);
    }

    /// @notice Supports recovering LP Rewards from other systems such as BAL to be distributed to holders
    /// or tokens that were mistakenly
    /// @param tokenAddress Address of the token to transfer
    /// @param to Address to give tokens to
    /// @param tokenAmount Amount of tokens to transfer
    function recoverERC20(
        address tokenAddress,
        address to,
        uint256 tokenAmount
    ) external override onlyRewardsDistribution {
        require(tokenAddress != address(rewardToken), "20");
        IERC20(tokenAddress).safeTransfer(to, tokenAmount);
        emit Recovered(tokenAddress, to, tokenAmount);
    }

    /// @notice Changes the `rewardsDistribution` associated to this contract
    /// @param _rewardsDistribution Address of the new rewards distributor contract
    /// @dev This function is part of the staking rewards interface and it is used to propagate
    /// a change of rewards distributor notified by the current `rewardsDistribution` address
    /// @dev It has already been checked in the `RewardsDistributor` contract calling
    /// this function that the `newRewardsDistributor` had a compatible reward token
    /// @dev With this function, everything is as if `rewardsDistribution` was admin of its own role
    function setNewRewardsDistribution(address _rewardsDistribution) external override onlyRewardsDistribution {
        rewardsDistribution = _rewardsDistribution;
        emit RewardsDistributionUpdated(_rewardsDistribution);
    }

    // ================================= Keepers ===================================

    /// @notice Updates all the fees not depending on individual HA conditions via keeper utils functions
    /// @param feeDeposit New deposit global fees
    /// @param feeWithdraw New withdraw global fees
    /// @dev Governance may decide to incorporate a collateral ratio dependence in the fees for HAs,
    /// in this case it will be done through the `FeeManager` contract
    /// @dev This dependence can either be a bonus or a malus
    function setFeeKeeper(uint64 feeDeposit, uint64 feeWithdraw) external override {
        require(msg.sender == address(_feeManager), "1");
        haBonusMalusDeposit = feeDeposit;
        haBonusMalusWithdraw = feeWithdraw;
    }

    // ======== Governance - Guardian Functions - Staking and Pauses ===============

    /// @notice Pauses the `getReward` method as well as the functions allowing to open, modify or close perpetuals
    /// @dev After calling this function, it is going to be impossible for HAs to interact with their perpetuals
    /// or claim their rewards on it
    function pause() external override onlyRole(GUARDIAN_ROLE) {
        _pause();
    }

    /// @notice Unpauses HAs functions
    function unpause() external override onlyRole(GUARDIAN_ROLE) {
        _unpause();
    }

    /// @notice Sets the conditions and specifies the duration of the reward distribution
    /// @param _rewardsDuration Duration for the rewards for this contract
    /// @param _rewardsDistribution Address which will give the reward tokens
    /// @dev It allows governance to directly change the rewards distribution contract and the conditions
    /// at which this distribution is done
    /// @dev The compatibility of the reward token is not checked here: it is checked
    /// in the rewards distribution contract when activating this as a staking contract,
    /// so if a reward distributor is set here but does not have a compatible reward token, then this reward
    /// distributor will not be able to set this contract as a staking contract
    function setRewardDistribution(uint256 _rewardsDuration, address _rewardsDistribution)
        external
        onlyRole(GUARDIAN_ROLE)
        zeroCheck(_rewardsDistribution)
    {
        rewardsDuration = _rewardsDuration;
        rewardsDistribution = _rewardsDistribution;
        emit RewardsDistributionDurationUpdated(rewardsDuration, rewardsDistribution);
    }

    // ============ Governance - Guardian Functions - Parameters ===================

    /// @notice Sets `baseURI` that is the URI to access ERC721 metadata
    /// @param _baseURI New `baseURI` parameter
    function setBaseURI(string memory _baseURI) external onlyRole(GUARDIAN_ROLE) {
        baseURI = _baseURI;
        emit BaseURIUpdated(_baseURI);
    }

    /// @notice Sets `lockTime` that is the minimum amount of time HAs have to stay within the protocol
    /// @param _lockTime New `lockTime` parameter
    /// @dev This parameter is used to prevent HAs from exiting before a certain amount of time and taking advantage
    /// of insiders' information they may have due to oracle latency
    function setLockTime(uint64 _lockTime) external override onlyRole(GUARDIAN_ROLE) {
        lockTime = _lockTime;
        emit LockTimeUpdated(_lockTime);
    }

    /// @notice Changes the maximum leverage authorized (commit/margin) and the maintenance margin under which
    /// perpetuals can be liquidated
    /// @param _maxLeverage New value of the maximum leverage allowed
    /// @param _maintenanceMargin The new maintenance margin
    /// @dev For a perpetual, the leverage is defined as the ratio between the committed amount and the margin
    /// @dev For a perpetual, the maintenance margin is defined as the ratio between the margin ratio / the committed amount
    function setBoundsPerpetual(uint64 _maxLeverage, uint64 _maintenanceMargin)
        external
        override
        onlyRole(GUARDIAN_ROLE)
        onlyCompatibleFees(_maintenanceMargin)
    {
        // Checking the compatibility of the parameters
        require(BASE_PARAMS**2 > _maxLeverage * _maintenanceMargin, "8");
        maxLeverage = _maxLeverage;
        maintenanceMargin = _maintenanceMargin;
        emit BoundsPerpetualUpdated(_maxLeverage, _maintenanceMargin);
    }

    /// @notice Sets `xHAFees` that is the thresholds of values of the ratio between what's covered (hedged)
    /// divided by what's to hedge with HAs at which fees will change as well as
    /// `yHAFees` that is the value of the deposit or withdraw fees at threshold
    /// @param _xHAFees Array of the x-axis value for the fees (deposit or withdraw)
    /// @param _yHAFees Array of the y-axis value for the fees (deposit or withdraw)
    /// @param deposit Whether deposit or withdraw fees should be updated
    /// @dev Evolution of the fees is linear between two values of thresholds
    /// @dev These x values should be ranked in ascending order
    /// @dev For deposit fees, the higher the x that is the ratio between what's to hedge and what's hedged
    /// the higher y should be (the more expensive it should be for HAs to come in)
    /// @dev For withdraw fees, evolution should follow an opposite logic
    function setHAFees(
        uint64[] memory _xHAFees,
        uint64[] memory _yHAFees,
        uint8 deposit
    ) external override onlyRole(GUARDIAN_ROLE) onlyCompatibleInputArrays(_xHAFees, _yHAFees) {
        if (deposit == 1) {
            xHAFeesDeposit = _xHAFees;
            yHAFeesDeposit = _yHAFees;
        } else {
            xHAFeesWithdraw = _xHAFees;
            yHAFeesWithdraw = _yHAFees;
        }
        emit HAFeesUpdated(_xHAFees, _yHAFees, deposit);
    }

    /// @notice Sets the target and limit proportions of collateral from users that can be insured by HAs
    /// @param _targetHAHedge Proportion of collateral from users that HAs should hedge
    /// @param _limitHAHedge Proportion of collateral from users above which HAs can see their perpetuals
    /// cashed out
    /// @dev `targetHAHedge` equal to `BASE_PARAMS` means that all the collateral from users should be insured by HAs
    /// @dev `targetHAHedge` equal to 0 means HA should not cover (hedge) anything
    function setTargetAndLimitHAHedge(uint64 _targetHAHedge, uint64 _limitHAHedge)
        external
        override
        onlyRole(GUARDIAN_ROLE)
        onlyCompatibleFees(_targetHAHedge)
        onlyCompatibleFees(_limitHAHedge)
    {
        require(_targetHAHedge <= _limitHAHedge, "8");
        limitHAHedge = _limitHAHedge;
        targetHAHedge = _targetHAHedge;
        // Updating the value in the `stableMaster` contract
        _stableMaster.setTargetHAHedge(_targetHAHedge);
        emit TargetAndLimitHAHedgeUpdated(_targetHAHedge, _limitHAHedge);
    }

    /// @notice Sets the portion of the leftover cash out amount of liquidated perpetuals that go to keepers
    /// @param _keeperFeesLiquidationRatio Proportion to keepers
    /// @dev This proportion should be inferior to `BASE_PARAMS`
    function setKeeperFeesLiquidationRatio(uint64 _keeperFeesLiquidationRatio)
        external
        override
        onlyRole(GUARDIAN_ROLE)
        onlyCompatibleFees(_keeperFeesLiquidationRatio)
    {
        keeperFeesLiquidationRatio = _keeperFeesLiquidationRatio;
        emit KeeperFeesLiquidationRatioUpdated(keeperFeesLiquidationRatio);
    }

    /// @notice Sets the maximum amounts going to the keepers when closing perpetuals
    /// because too much was hedged by HAs or when liquidating a perpetual
    /// @param _keeperFeesLiquidationCap Maximum reward going to the keeper liquidating a perpetual
    /// @param _keeperFeesClosingCap Maximum reward going to the keeper forcing the closing of an ensemble
    /// of perpetuals
    function setKeeperFeesCap(uint256 _keeperFeesLiquidationCap, uint256 _keeperFeesClosingCap)
        external
        override
        onlyRole(GUARDIAN_ROLE)
    {
        keeperFeesLiquidationCap = _keeperFeesLiquidationCap;
        keeperFeesClosingCap = _keeperFeesClosingCap;
        emit KeeperFeesCapUpdated(keeperFeesLiquidationCap, keeperFeesClosingCap);
    }

    /// @notice Sets the x-array (ie thresholds) for `FeeManager` when closing perpetuals and the y-array that is the
    /// value of the proportions of the fees going to keepers closing perpetuals
    /// @param _xKeeperFeesClosing Thresholds for closing fees
    /// @param _yKeeperFeesClosing Value of the fees at the different threshold values specified in `xKeeperFeesClosing`
    /// @dev The x thresholds correspond to values of the hedge ratio divided by two
    /// @dev `xKeeperFeesClosing` and `yKeeperFeesClosing` should have the same length
    function setKeeperFeesClosing(uint64[] memory _xKeeperFeesClosing, uint64[] memory _yKeeperFeesClosing)
        external
        override
        onlyRole(GUARDIAN_ROLE)
        onlyCompatibleInputArrays(_xKeeperFeesClosing, _yKeeperFeesClosing)
    {
        xKeeperFeesClosing = _xKeeperFeesClosing;
        yKeeperFeesClosing = _yKeeperFeesClosing;
        emit KeeperFeesClosingUpdated(xKeeperFeesClosing, yKeeperFeesClosing);
    }

    // ================ Governance - `PoolManager` Functions =======================

    /// @notice Changes the reference to the `FeeManager` contract
    /// @param feeManager_ New `FeeManager` contract
    /// @dev This allows the `PoolManager` contract to propagate changes to the `PerpetualManager`
    /// @dev This is the only place where the `_feeManager` can be changed, it is as if there was
    /// a `FEEMANAGER_ROLE` for which `PoolManager` was the admin
    function setFeeManager(IFeeManager feeManager_) external override onlyRole(POOLMANAGER_ROLE) {
        _feeManager = feeManager_;
    }

    // ======================= `StableMaster` Function =============================

    /// @notice Changes the oracle contract used to compute collateral price with respect to the stablecoin's price
    /// @param oracle_ Oracle contract
    /// @dev The collateral `PoolManager` does not store a reference to an oracle, the value of the oracle
    /// is hence directly set by the `StableMaster`
    function setOracle(IOracle oracle_) external override {
        require(msg.sender == address(_stableMaster), "1");
        oracle = oracle_;
    }
}


// File contracts/perpetualManager/PerpetualManagerFront.sol



pragma solidity ^0.8.7;

/// @title PerpetualManagerFront
/// @author Angle Core Team
/// @notice `PerpetualManager` is the contract handling all the Hedging Agents perpetuals
/// @dev There is one `PerpetualManager` contract per pair stablecoin/collateral in the protocol
/// @dev This file contains the functions of the `PerpetualManager` that can be directly interacted
/// with by external agents. These functions are the ones that need to be called to open, modify or close
/// perpetuals
/// @dev `PerpetualManager` naturally handles staking, the code allowing HAs to stake has been inspired from
/// https://github.com/SetProtocol/index-coop-contracts/blob/master/contracts/staking/StakingRewardsV2.sol
/// @dev Perpetuals at Angle protocol are treated as NFTs, this contract handles the logic for that
contract PerpetualManagerFront is PerpetualManager, IPerpetualManagerFront {
    using SafeERC20 for IERC20;
    using CountersUpgradeable for CountersUpgradeable.Counter;

    // =============================== Deployer ====================================

    /// @notice Initializes the `PerpetualManager` contract
    /// @param poolManager_ Reference to the `PoolManager` contract handling the collateral associated to the `PerpetualManager`
    /// @param rewardToken_ Reference to the `rewardtoken` that can be distributed to HAs as they have open positions
    /// @dev The reward token is most likely going to be the ANGLE token
    /// @dev Since this contract is upgradeable, this function is an `initialize` and not a `constructor`
    /// @dev Zero checks are only performed on addresses for which no external calls are made, in this case just
    /// the `rewardToken_` is checked
    /// @dev After initializing this contract, all the fee parameters should be initialized by governance using
    /// the setters in this contract
    function initialize(IPoolManager poolManager_, IERC20 rewardToken_)
        external
        initializer
        zeroCheck(address(rewardToken_))
    {
        // Initializing contracts
        __Pausable_init();
        __AccessControl_init();

        // Creating references
        poolManager = poolManager_;
        _token = IERC20(poolManager_.token());
        _stableMaster = IStableMaster(poolManager_.stableMaster());
        rewardToken = rewardToken_;
        _collatBase = 10**(IERC20Metadata(address(_token)).decimals());
        // The references to the `feeManager` and to the `oracle` contracts are to be set when the contract is deployed

        // Setting up Access Control for this contract
        // There is no need to store the reference to the `PoolManager` address here
        // Once the `POOLMANAGER_ROLE` has been granted, no new addresses can be granted or revoked
        // from this role: a `PerpetualManager` contract can only have one `PoolManager` associated
        _setupRole(POOLMANAGER_ROLE, address(poolManager));
        // `PoolManager` is admin of all the roles. Most of the time, changes are propagated from it
        _setRoleAdmin(GUARDIAN_ROLE, POOLMANAGER_ROLE);
        _setRoleAdmin(POOLMANAGER_ROLE, POOLMANAGER_ROLE);
        // Pausing the contract because it is not functional till the collateral has really been deployed by the
        // `StableMaster`
        _pause();
    }

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() initializer {}

    // ================================= HAs =======================================

    /// @notice Lets a HA join the protocol and create a perpetual
    /// @param owner Address of the future owner of the perpetual
    /// @param margin Amount of collateral brought by the HA
    /// @param committedAmount Amount of collateral covered by the HA
    /// @param maxOracleRate Maximum oracle value that the HA wants to see stored in the perpetual
    /// @param minNetMargin Minimum net margin that the HA is willing to see stored in the perpetual
    /// @return perpetualID The ID of the perpetual opened by this HA
    /// @dev The future owner of the perpetual cannot be the zero address
    /// @dev It is possible to open a perpetual on behalf of someone else
    /// @dev The `maxOracleRate` parameter serves as a protection against oracle manipulations for HAs opening perpetuals
    /// @dev `minNetMargin` is a protection against too big variations in the fees for HAs
    function openPerpetual(
        address owner,
        uint256 margin,
        uint256 committedAmount,
        uint256 maxOracleRate,
        uint256 minNetMargin
    ) external override whenNotPaused zeroCheck(owner) returns (uint256 perpetualID) {
        // Transaction will revert anyway if `margin` is zero
        require(committedAmount > 0, "27");

        // There could be a reentrancy attack as a call to an external contract is done before state variables
        // updates. Yet in this case, the call involves a transfer from the `msg.sender` to the contract which
        // eliminates the risk
        _token.safeTransferFrom(msg.sender, address(poolManager), margin);

        // Computing the oracle value
        // Only the highest oracle value (between Chainlink and Uniswap) we get is stored in the perpetual
        (, uint256 rateUp) = _getOraclePrice();
        // Checking if the oracle rate is not too big: a too big oracle rate could mean for a HA that the price
        // has become too high to make it interesting to open a perpetual
        require(rateUp <= maxOracleRate, "28");

        // Computing the total amount of stablecoins that this perpetual is going to hedge for the protocol
        uint256 totalHedgeAmountUpdate = (committedAmount * rateUp) / _collatBase;
        // Computing the net amount brought by the HAs to store in the perpetual
        uint256 netMargin = _getNetMargin(margin, totalHedgeAmountUpdate, committedAmount);
        require(netMargin >= minNetMargin, "29");
        // Checking if the perpetual is not too leveraged, even after computing the fees
        require((committedAmount * BASE_PARAMS) <= maxLeverage * netMargin, "30");

        // ERC721 logic
        _perpetualIDcount.increment();
        perpetualID = _perpetualIDcount.current();

        // In the logic of the staking contract, the `_updateReward` should be called
        // before the perpetual is opened
        _updateReward(perpetualID, 0);

        // Updating the total amount of stablecoins hedged by HAs and creating the perpetual
        totalHedgeAmount += totalHedgeAmountUpdate;

        perpetualData[perpetualID] = Perpetual(rateUp, block.timestamp, netMargin, committedAmount);

        // Following ERC721 logic, the function `_mint(...)` calls `_checkOnERC721Received` and could then be used as
        // a reentrancy vector. Minting should then only be done at the very end after updating all variables.
        _mint(owner, perpetualID);
        emit PerpetualOpened(perpetualID, rateUp, netMargin, committedAmount);
    }

    /// @notice Lets a HA close a perpetual owned or controlled for the stablecoin/collateral pair associated
    /// to this `PerpetualManager` contract
    /// @param perpetualID ID of the perpetual to close
    /// @param to Address which will receive the proceeds from this perpetual
    /// @param minCashOutAmount Minimum net cash out amount that the HA is willing to get for closing the
    /// perpetual
    /// @dev The HA gets the current amount of her position depending on the entry oracle value
    /// and current oracle value minus some transaction fees computed on the committed amount
    /// @dev `msg.sender` should be the owner of `perpetualID` or be approved for this perpetual
    /// @dev If the `PoolManager` does not have enough collateral, the perpetual owner will be converted to a SLP and
    /// receive sanTokens
    /// @dev The `minCashOutAmount` serves as a protection for HAs closing their perpetuals: it protects them both
    /// from fees that would have become too high and from a too big decrease in oracle value
    function closePerpetual(
        uint256 perpetualID,
        address to,
        uint256 minCashOutAmount
    ) external override whenNotPaused onlyApprovedOrOwner(msg.sender, perpetualID) {
        // Loading perpetual data and getting the oracle price
        Perpetual memory perpetual = perpetualData[perpetualID];
        (uint256 rateDown, ) = _getOraclePrice();
        // The lowest oracle price between Chainlink and Uniswap is used to compute the perpetual's position at
        // the time of closing: it is the one that is most at the advantage of the protocol
        (uint256 cashOutAmount, uint256 liquidated) = _checkLiquidation(perpetualID, perpetual, rateDown);
        if (liquidated == 0) {
            // You need to wait `lockTime` before being able to withdraw funds from the protocol as a HA
            require(perpetual.entryTimestamp + lockTime <= block.timestamp, "31");
            // Cashing out the perpetual internally
            _closePerpetual(perpetualID, perpetual);
            // Computing exit fees: they depend on how much is already hedgeded by HAs compared with what's to hedge
            (uint256 netCashOutAmount, ) = _getNetCashOutAmount(
                cashOutAmount,
                perpetual.committedAmount,
                // The perpetual has already been cashed out when calling this function, so there is no
                // `committedAmount` to add to the `totalHedgeAmount` to get the `currentHedgeAmount`
                _computeHedgeRatio(totalHedgeAmount)
            );
            require(netCashOutAmount >= minCashOutAmount, "32");
            emit PerpetualClosed(perpetualID, netCashOutAmount);
            _secureTransfer(to, netCashOutAmount);
        }
    }

    /// @notice Lets a HA increase the `margin` in a perpetual she controls for this
    /// stablecoin/collateral pair
    /// @param perpetualID ID of the perpetual to which amount should be added to `margin`
    /// @param amount Amount to add to the perpetual's `margin`
    /// @dev This decreases the leverage multiple of this perpetual
    /// @dev If this perpetual is to be liquidated, the HA is not going to be able to add liquidity to it
    /// @dev Since this function can be used to add liquidity to a perpetual, there is no need to restrict
    /// it to the owner of the perpetual
    /// @dev Calling this function on a non-existing perpetual makes it revert
    function addToPerpetual(uint256 perpetualID, uint256 amount) external override whenNotPaused {
        // Loading perpetual data and getting the oracle price
        Perpetual memory perpetual = perpetualData[perpetualID];
        (uint256 rateDown, ) = _getOraclePrice();
        (, uint256 liquidated) = _checkLiquidation(perpetualID, perpetual, rateDown);
        if (liquidated == 0) {
            // Overflow check
            _token.safeTransferFrom(msg.sender, address(poolManager), amount);
            perpetualData[perpetualID].margin += amount;
            emit PerpetualUpdated(perpetualID, perpetual.margin + amount);
        }
    }

    /// @notice Lets a HA decrease the `margin` in a perpetual she controls for this
    /// stablecoin/collateral pair
    /// @param perpetualID ID of the perpetual from which collateral should be removed
    /// @param amount Amount to remove from the perpetual's `margin`
    /// @param to Address which will receive the collateral removed from this perpetual
    /// @dev This increases the leverage multiple of this perpetual
    /// @dev `msg.sender` should be the owner of `perpetualID` or be approved for this perpetual
    function removeFromPerpetual(
        uint256 perpetualID,
        uint256 amount,
        address to
    ) external override whenNotPaused onlyApprovedOrOwner(msg.sender, perpetualID) {
        // Loading perpetual data and getting the oracle price
        Perpetual memory perpetual = perpetualData[perpetualID];
        (uint256 rateDown, ) = _getOraclePrice();

        (uint256 cashOutAmount, uint256 liquidated) = _checkLiquidation(perpetualID, perpetual, rateDown);
        if (liquidated == 0) {
            // Checking if money can be withdrawn from the perpetual
            require(
                // The perpetual should not have been opened too soon
                (perpetual.entryTimestamp + lockTime <= block.timestamp) &&
                    // The amount to withdraw should not be more important than the perpetual's `cashOutAmount` and `margin`
                    (amount < cashOutAmount) &&
                    (amount < perpetual.margin) &&
                    // Withdrawing collateral should not make the leverage of the perpetual too important
                    // Checking both on `cashOutAmount` and `perpetual.margin` (as we can have either
                    // `cashOutAmount >= perpetual.margin` or `cashOutAmount<perpetual.margin`)
                    // No checks are done on `maintenanceMargin`, as conditions on `maxLeverage` are more restrictive
                    perpetual.committedAmount * BASE_PARAMS <= (cashOutAmount - amount) * maxLeverage &&
                    perpetual.committedAmount * BASE_PARAMS <= (perpetual.margin - amount) * maxLeverage,
                "33"
            );
            perpetualData[perpetualID].margin -= amount;
            emit PerpetualUpdated(perpetualID, perpetual.margin - amount);

            _secureTransfer(to, amount);
        }
    }

    /// @notice Allows an outside caller to liquidate perpetuals if their margin ratio is
    /// under the maintenance margin
    /// @param perpetualIDs ID of the targeted perpetuals
    /// @dev Liquidation of a perpetual will succeed if the `cashOutAmount` of the perpetual is under the maintenance margin,
    /// and nothing will happen if the perpetual is still healthy
    /// @dev The outside caller (namely a keeper) gets a portion of the leftover cash out amount of the perpetual
    /// @dev As keepers may directly profit from this function, there may be front-running problems with miners bots,
    /// we may have to put an access control logic for this function to only allow white-listed addresses to act
    /// as keepers for the protocol
    function liquidatePerpetuals(uint256[] memory perpetualIDs) external override whenNotPaused {
        // Getting the oracle price
        (uint256 rateDown, ) = _getOraclePrice();
        uint256 liquidationFees;
        for (uint256 i = 0; i < perpetualIDs.length; i++) {
            uint256 perpetualID = perpetualIDs[i];
            if (_exists(perpetualID)) {
                // Loading perpetual data
                Perpetual memory perpetual = perpetualData[perpetualID];
                (uint256 cashOutAmount, uint256 liquidated) = _checkLiquidation(perpetualID, perpetual, rateDown);
                if (liquidated == 1) {
                    // Computing the incentive for the keeper as a function of the `cashOutAmount` of the perpetual
                    // This incentivizes keepers to react fast when the price starts to go below the liquidation
                    // margin
                    liquidationFees += _computeKeeperLiquidationFees(cashOutAmount);
                }
            }
        }
        emit KeeperTransferred(msg.sender, liquidationFees);
        _secureTransfer(msg.sender, liquidationFees);
    }

    /// @notice Allows an outside caller to close perpetuals if too much of the collateral from
    /// users is hedged by HAs
    /// @param perpetualIDs IDs of the targeted perpetuals
    /// @dev This function allows to make sure that the protocol will not have too much HAs for a long period of time
    /// @dev A HA that owns a targeted perpetual will get the current value of her perpetual
    /// @dev The call to the function above will revert if HAs cannot be cashed out
    /// @dev As keepers may directly profit from this function, there may be front-running problems with miners bots,
    /// we may have to put an access control logic for this function to only allow white-listed addresses to act
    /// as keepers for the protocol
    function forceClosePerpetuals(uint256[] memory perpetualIDs) external override whenNotPaused {
        // Getting the oracle prices
        // `rateUp` is used to compute the cost of manipulation of the covered amounts
        (uint256 rateDown, uint256 rateUp) = _getOraclePrice();

        // Fetching `stocksUsers` to check if perpetuals cover too much collateral
        uint256 stocksUsers = _stableMaster.getStocksUsers();
        uint256 targetHedgeAmount = (stocksUsers * targetHAHedge) / BASE_PARAMS;

        // `totalHedgeAmount` should be greater than the limit hedge amount
        require(totalHedgeAmount > (stocksUsers * limitHAHedge) / BASE_PARAMS, "34");
        uint256 liquidationFees;
        uint256 cashOutFees;

        // Array of pairs `(owner, netCashOutAmount)`
        Pairs[] memory outputPairs = new Pairs[](perpetualIDs.length);

        for (uint256 i = 0; i < perpetualIDs.length; i++) {
            uint256 perpetualID = perpetualIDs[i];
            address owner = _owners[perpetualID];
            if (owner != address(0)) {
                // Loading perpetual data and getting the oracle price
                Perpetual memory perpetual = perpetualData[perpetualID];
                // First checking if the perpetual should not be liquidated
                (uint256 cashOutAmount, uint256 liquidated) = _checkLiquidation(perpetualID, perpetual, rateDown);
                if (liquidated == 1) {
                    // This results in the perpetual being liquidated and the keeper being paid the same amount of fees as
                    // what would have been paid if the perpetual had been liquidated using the `liquidatePerpetualFunction`
                    // Computing the incentive for the keeper as a function of the `cashOutAmount` of the perpetual
                    // This incentivizes keepers to react fast
                    liquidationFees += _computeKeeperLiquidationFees(cashOutAmount);
                } else if (perpetual.entryTimestamp + lockTime <= block.timestamp) {
                    // It is impossible to force the closing a perpetual that was just created: in the other case, this
                    // function could be used to do some insider trading and to bypass the `lockTime` limit
                    // If too much collateral is hedged by HAs, then the perpetual can be cashed out
                    _closePerpetual(perpetualID, perpetual);
                    uint64 ratioPostCashOut;
                    // In this situation, `totalHedgeAmount` is the `currentHedgeAmount`
                    if (targetHedgeAmount > totalHedgeAmount) {
                        ratioPostCashOut = uint64((totalHedgeAmount * BASE_PARAMS) / targetHedgeAmount);
                    } else {
                        ratioPostCashOut = uint64(BASE_PARAMS);
                    }
                    // Computing how much the HA will get and the amount of fees paid at closing
                    (uint256 netCashOutAmount, uint256 fees) = _getNetCashOutAmount(
                        cashOutAmount,
                        perpetual.committedAmount,
                        ratioPostCashOut
                    );
                    cashOutFees += fees;
                    // Storing the owners of perpetuals that were forced cash out in a memory array to avoid
                    // reentrancy attacks
                    outputPairs[i] = Pairs(owner, netCashOutAmount);
                }

                // Checking if at this point enough perpetuals have been cashed out
                if (totalHedgeAmount <= targetHedgeAmount) break;
            }
        }

        uint64 ratio = (targetHedgeAmount == 0)
            ? 0
            : uint64((totalHedgeAmount * BASE_PARAMS) / (2 * targetHedgeAmount));
        // Computing the rewards given to the keeper calling this function
        // and transferring the rewards to the keeper
        // Using a cache value of `cashOutFees` to save some gas
        // The value below is the amount of fees that should go to the keeper forcing the closing of perpetuals
        // In the linear by part function, if `xKeeperFeesClosing` is greater than 0.5 (meaning we are not at target yet)
        // then keepers should get almost no fees
        cashOutFees = (cashOutFees * _piecewiseLinear(ratio, xKeeperFeesClosing, yKeeperFeesClosing)) / BASE_PARAMS;
        // The amount of fees that can go to keepers is capped by a parameter set by governance
        cashOutFees = cashOutFees < keeperFeesClosingCap ? cashOutFees : keeperFeesClosingCap;
        // A malicious attacker could take advantage of this function to take a flash loan, burn agTokens
        // to diminish the stocks users and then force close some perpetuals. We also need to check that assuming
        // really small burn transaction fees (of 0.05%), an attacker could make a profit with such flash loan
        // if current hedge is below the target hedge by making such flash loan.
        // The formula for the cost of such flash loan is:
        // `fees * (limitHAHedge - targetHAHedge) * stocksUsers / oracle`
        // In order to avoid doing multiplications after divisions, and to get everything in the correct base, we do:
        uint256 estimatedCost = (5 * (limitHAHedge - targetHAHedge) * stocksUsers * _collatBase) /
            (rateUp * 10000 * BASE_PARAMS);
        cashOutFees = cashOutFees < estimatedCost ? cashOutFees : estimatedCost;

        emit PerpetualsForceClosed(perpetualIDs, outputPairs, msg.sender, cashOutFees + liquidationFees);

        // Processing transfers after all calculations have been performed
        for (uint256 j = 0; j < perpetualIDs.length; j++) {
            if (outputPairs[j].netCashOutAmount > 0) {
                _secureTransfer(outputPairs[j].owner, outputPairs[j].netCashOutAmount);
            }
        }
        _secureTransfer(msg.sender, cashOutFees + liquidationFees);
    }

    // =========================== External View Function ==========================

    /// @notice Returns the `cashOutAmount` of the perpetual owned by someone at a given oracle value
    /// @param perpetualID ID of the perpetual
    /// @param rate Oracle value
    /// @return The `cashOutAmount` of the perpetual
    /// @return Whether the position of the perpetual is now too small compared with its initial position and should hence
    /// be liquidated
    /// @dev This function is used by the Collateral Settlement contract
    function getCashOutAmount(uint256 perpetualID, uint256 rate) external view override returns (uint256, uint256) {
        Perpetual memory perpetual = perpetualData[perpetualID];
        return _getCashOutAmount(perpetual, rate);
    }

    // =========================== Reward Distribution =============================

    /// @notice Allows to check the amount of reward tokens earned by a perpetual
    /// @param perpetualID ID of the perpetual to check
    function earned(uint256 perpetualID) external view returns (uint256) {
        return _earned(perpetualID, perpetualData[perpetualID].committedAmount * perpetualData[perpetualID].entryRate);
    }

    /// @notice Allows a perpetual owner to withdraw rewards
    /// @param perpetualID ID of the perpetual which accumulated tokens
    /// @dev Only an approved caller can claim the rewards for the perpetual with perpetualID
    function getReward(uint256 perpetualID) external whenNotPaused onlyApprovedOrOwner(msg.sender, perpetualID) {
        _getReward(perpetualID, perpetualData[perpetualID].committedAmount * perpetualData[perpetualID].entryRate);
    }

    // =============================== ERC721 logic ================================

    /// @notice Gets the name of the NFT collection implemented by this contract
    function name() external pure override returns (string memory) {
        return "AnglePerp";
    }

    /// @notice Gets the symbol of the NFT collection implemented by this contract
    function symbol() external pure override returns (string memory) {
        return "AnglePerp";
    }

    /// @notice Gets the URI containing metadata
    /// @param perpetualID ID of the perpetual
    function tokenURI(uint256 perpetualID) external view override returns (string memory) {
        require(_exists(perpetualID), "2");
        // There is no perpetual with `perpetualID` equal to 0, so the following variable is
        // always greater than zero
        uint256 temp = perpetualID;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (perpetualID != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(perpetualID % 10)));
            perpetualID /= 10;
        }
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, string(buffer))) : "";
    }

    /// @notice Gets the balance of an owner
    /// @param owner Address of the owner
    /// @dev Balance here represents the number of perpetuals owned by a HA
    function balanceOf(address owner) external view override returns (uint256) {
        require(owner != address(0), "0");
        return _balances[owner];
    }

    /// @notice Gets the owner of the perpetual with ID perpetualID
    /// @param perpetualID ID of the perpetual
    function ownerOf(uint256 perpetualID) external view override returns (address) {
        return _ownerOf(perpetualID);
    }

    /// @notice Approves to an address specified by `to` a perpetual specified by `perpetualID`
    /// @param to Address to approve the perpetual to
    /// @param perpetualID ID of the perpetual
    /// @dev The approved address will have the right to transfer the perpetual, to cash it out
    /// on behalf of the owner, to add or remove collateral in it and to choose the destination
    /// address that will be able to receive the proceeds of the perpetual
    function approve(address to, uint256 perpetualID) external override {
        address owner = _ownerOf(perpetualID);
        require(to != owner, "35");
        require(msg.sender == owner || isApprovedForAll(owner, msg.sender), "21");

        _approve(to, perpetualID);
    }

    /// @notice Gets the approved address by a perpetual owner
    /// @param perpetualID ID of the concerned perpetual
    function getApproved(uint256 perpetualID) external view override returns (address) {
        require(_exists(perpetualID), "2");
        return _getApproved(perpetualID);
    }

    /// @notice Sets approval on all perpetuals owned by the owner to an operator
    /// @param operator Address to approve (or block) on all perpetuals
    /// @param approved Whether the sender wants to approve or block the operator
    function setApprovalForAll(address operator, bool approved) external override {
        require(operator != msg.sender, "36");
        _operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /// @notice Gets if the operator address is approved on all perpetuals by the owner
    /// @param owner Owner of perpetuals
    /// @param operator Address to check if approved
    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /// @notice Gets if the sender address is approved for the perpetualId
    /// @param perpetualID ID of the perpetual
    function isApprovedOrOwner(address spender, uint256 perpetualID) external view override returns (bool) {
        return _isApprovedOrOwner(spender, perpetualID);
    }

    /// @notice Transfers the `perpetualID` from an address to another
    /// @param from Source address
    /// @param to Destination a address
    /// @param perpetualID ID of the perpetual to transfer
    function transferFrom(
        address from,
        address to,
        uint256 perpetualID
    ) external override onlyApprovedOrOwner(msg.sender, perpetualID) {
        _transfer(from, to, perpetualID);
    }

    /// @notice Safely transfers the `perpetualID` from an address to another without data in it
    /// @param from Source address
    /// @param to Destination a address
    /// @param perpetualID ID of the perpetual to transfer
    function safeTransferFrom(
        address from,
        address to,
        uint256 perpetualID
    ) external override {
        safeTransferFrom(from, to, perpetualID, "");
    }

    /// @notice Safely transfers the `perpetualID` from an address to another with data in the transfer
    /// @param from Source address
    /// @param to Destination a address
    /// @param perpetualID ID of the perpetual to transfer
    function safeTransferFrom(
        address from,
        address to,
        uint256 perpetualID,
        bytes memory _data
    ) public override onlyApprovedOrOwner(msg.sender, perpetualID) {
        _safeTransfer(from, to, perpetualID, _data);
    }

    // =============================== ERC165 logic ================================

    /// @notice Queries if a contract implements an interface
    /// @param interfaceId The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function uses less than 30,000 gas.
    /// Required by the ERC721 standard, so used to check that the IERC721 is implemented.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceId) external pure override(IERC165) returns (bool) {
        return
            interfaceId == type(IPerpetualManagerFront).interfaceId ||
            interfaceId == type(IPerpetualManagerFunctions).interfaceId ||
            interfaceId == type(IStakingRewards).interfaceId ||
            interfaceId == type(IStakingRewardsFunctions).interfaceId ||
            interfaceId == type(IAccessControl).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC165).interfaceId;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_baseURI","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_maxLeverage","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"_maintenanceMargin","type":"uint64"}],"name":"BoundsPerpetualUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64[]","name":"_xHAFees","type":"uint64[]"},{"indexed":false,"internalType":"uint64[]","name":"_yHAFees","type":"uint64[]"},{"indexed":false,"internalType":"uint8","name":"deposit","type":"uint8"}],"name":"HAFeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_keeperFeesLiquidationCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_keeperFeesClosingCap","type":"uint256"}],"name":"KeeperFeesCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64[]","name":"xKeeperFeesClosing","type":"uint64[]"},{"indexed":false,"internalType":"uint64[]","name":"yKeeperFeesClosing","type":"uint64[]"}],"name":"KeeperFeesClosingUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_keeperFeesLiquidationRatio","type":"uint64"}],"name":"KeeperFeesLiquidationRatioUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"keeperAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidationFees","type":"uint256"}],"name":"KeeperTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_lockTime","type":"uint64"}],"name":"LockTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_perpetualID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_closeAmount","type":"uint256"}],"name":"PerpetualClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_perpetualID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_entryRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_margin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_committedAmount","type":"uint256"}],"name":"PerpetualOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_perpetualID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_margin","type":"uint256"}],"name":"PerpetualUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"perpetualIDs","type":"uint256[]"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"netCashOutAmount","type":"uint256"}],"indexed":false,"internalType":"struct Pairs[]","name":"ownerAndCashOut","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"keeper","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"PerpetualsForceClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_reward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":false,"internalType":"uint256","name":"_reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_rewardsDuration","type":"uint256"},{"indexed":true,"internalType":"address","name":"_rewardsDistributor","type":"address"}],"name":"RewardsDistributionDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_rewardsDistributor","type":"address"}],"name":"RewardsDistributionUpdated","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":false,"internalType":"uint64","name":"_targetHAHedge","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"_limitHAHedge","type":"uint64"}],"name":"TargetAndLimitHAHedgeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BASE_PARAMS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARDIAN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOLMANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addToPerpetual","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minCashOutAmount","type":"uint256"}],"name":"closePerpetual","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"governorList","type":"address[]"},{"internalType":"address","name":"guardian","type":"address"},{"internalType":"contract IFeeManager","name":"feeManager_","type":"address"},{"internalType":"contract IOracle","name":"oracle_","type":"address"}],"name":"deployCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"perpetualIDs","type":"uint256[]"}],"name":"forceClosePerpetuals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"getCashOutAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","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":[],"name":"haBonusMalusDeposit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"haBonusMalusWithdraw","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","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":"contract IPoolManager","name":"poolManager_","type":"address"},{"internalType":"contract IERC20","name":"rewardToken_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"isApprovedOrOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeperFeesClosingCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeperFeesLiquidationCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeperFeesLiquidationRatio","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitHAHedge","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"perpetualIDs","type":"uint256[]"}],"name":"liquidatePerpetuals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maintenanceMargin","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLeverage","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"margin","type":"uint256"},{"internalType":"uint256","name":"committedAmount","type":"uint256"},{"internalType":"uint256","name":"maxOracleRate","type":"uint256"},{"internalType":"uint256","name":"minNetMargin","type":"uint256"}],"name":"openPerpetual","outputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"perpetualData","outputs":[{"internalType":"uint256","name":"entryRate","type":"uint256"},{"internalType":"uint256","name":"entryTimestamp","type":"uint256"},{"internalType":"uint256","name":"margin","type":"uint256"},{"internalType":"uint256","name":"committedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"perpetualRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolManager","outputs":[{"internalType":"contract IPoolManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"removeFromPerpetual","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDistribution","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"perpetualID","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_maxLeverage","type":"uint64"},{"internalType":"uint64","name":"_maintenanceMargin","type":"uint64"}],"name":"setBoundsPerpetual","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"feeDeposit","type":"uint64"},{"internalType":"uint64","name":"feeWithdraw","type":"uint64"}],"name":"setFeeKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IFeeManager","name":"feeManager_","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"_xHAFees","type":"uint64[]"},{"internalType":"uint64[]","name":"_yHAFees","type":"uint64[]"},{"internalType":"uint8","name":"deposit","type":"uint8"}],"name":"setHAFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_keeperFeesLiquidationCap","type":"uint256"},{"internalType":"uint256","name":"_keeperFeesClosingCap","type":"uint256"}],"name":"setKeeperFeesCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"_xKeeperFeesClosing","type":"uint64[]"},{"internalType":"uint64[]","name":"_yKeeperFeesClosing","type":"uint64[]"}],"name":"setKeeperFeesClosing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_keeperFeesLiquidationRatio","type":"uint64"}],"name":"setKeeperFeesLiquidationRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_lockTime","type":"uint64"}],"name":"setLockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardsDistribution","type":"address"}],"name":"setNewRewardsDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOracle","name":"oracle_","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardsDuration","type":"uint256"},{"internalType":"address","name":"_rewardsDistribution","type":"address"}],"name":"setRewardDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_targetHAHedge","type":"uint64"},{"internalType":"uint64","name":"_limitHAHedge","type":"uint64"}],"name":"setTargetAndLimitHAHedge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"targetHAHedge","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalHedgeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"perpetualID","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"xHAFeesDeposit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"xHAFeesWithdraw","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"xKeeperFeesClosing","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"yHAFeesDeposit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"yHAFeesWithdraw","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"yKeeperFeesClosing","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b50602154610100900460ff16806200002c575060215460ff16155b620000945760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b602154610100900460ff16158015620000b7576021805461ffff19166101011790555b8015620000ca576021805461ff00191690555b50615fff80620000db6000396000f3fe608060405234801561001057600080fd5b50600436106104a15760003560e01c80637bd06a151161026d578063c0212c7211610151578063df136d65116100ce578063e985e9c511610092578063e985e9c514610aba578063ebe2b12b14610af4578063f301af4214610afd578063f5d011c514610b1d578063f7c618c114610b30578063f902fad714610b4357600080fd5b8063df136d6514610a54578063df1b8bd314610a5d578063e048684214610a6c578063e2b01a5e14610a94578063e5234c7a14610aa757600080fd5b8063d1aace9f11610115578063d1aace9f146109f5578063d547741f14610a08578063d5eb058114610a1b578063d7f6328e14610a2e578063dc4c90d314610a4157600080fd5b8063c0212c72146109a0578063c1618dda146109b3578063c628a6f7146109c6578063c87b56dd146109d9578063c8f33c91146109ec57600080fd5b806395d89b41116101ea578063ae3302c2116101ae578063ae3302c214610931578063b126e7e51461094b578063b3b1cb271461095e578063b88d4fde14610971578063b8f3689514610984578063bcb01a801461098d57600080fd5b806395d89b41146104ce5780639f48118f146108f8578063a217fddf14610903578063a22cb4651461090b578063a62b2a3d1461091e57600080fd5b8063873291bb11610231578063873291bb1461086f5780638c6dfaf7146108825780638d5e19f11461088b5780638e240144146108a557806391d14854146108bf57600080fd5b80637bd06a15146108185780637dc0d1d0146108215780638211477a14610834578063840a7698146108475780638456cb591461086757600080fd5b8063386a9525116103945780634d6ed8c4116103115780636c0360eb116102d55780636c0360eb146107bb5780636d59dae7146107c357806370a08231146107d65780637adbf973146107e95780637b0a47ee146107fc5780637b39ecf71461080557600080fd5b80634d6ed8c414610764578063515dc4801461077757806355f804b31461078a5780635c975abb1461079d5780636352211e146107a857600080fd5b8063430c208111610358578063430c208114610705578063472d35b91461071857806347c12e011461072b578063485cc9551461073e57806349a5d3ef1461075157600080fd5b8063386a9525146106bb5780633c6b16ab146106c45780633f4ba83a146106d75780633fc6df6e146106df57806342842e0e146106f257600080fd5b806323b872dd11610422578063324f3815116103e6578063324f38151461065557806336568abe1461066f5780633675441514610682578063367f21b41461069557806338050129146106a857600080fd5b806323b872dd146105e4578063248a9ca3146105f757806324d83b791461061a57806324ea54f41461062d5780632f2ff15d1461064257600080fd5b80630c016dc0116104695780630c016dc01461056e5780630d668087146105915780631171bda9146105ab578063142c3ba0146105be5780631c4b774b146105d157600080fd5b806301ffc9a7146104a657806306fdde03146104ce578063081812fc146104fc578063095ea7b3146105275780630bfab8a71461053c575b600080fd5b6104b96104b43660046155ba565b610b98565b60405190151581526020015b60405180910390f35b6040805180820190915260098152680416e676c65506572760bc1b60208201525b6040516104c59190615b3d565b61050f61050a36600461557c565b610c71565b6040516001600160a01b0390911681526020016104c5565b61053a6105353660046152ab565b610cdb565b005b600e5461055690600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020016104c5565b610583600080516020615f8a83398151915281565b6040519081526020016104c5565b600e5461055690600160801b90046001600160401b031681565b61053a6105b93660046151bd565b610d92565b6105566105cc36600461557c565b610e65565b61053a6105df36600461557c565b610ea2565b61053a6105f23660046151bd565b610f18565b61058361060536600461557c565b60009081526022602052604090206001015490565b61053a61062836600461567c565b610f52565b610583600080516020615faa83398151915281565b61053a610650366004615595565b61106d565b600d5461055690600160c01b90046001600160401b031681565b61053a61067d366004615595565b611093565b61053a6106903660046156f0565b6110de565b61053a6106a3366004615485565b61115a565b6105566106b636600461557c565b611361565b61058360155481565b61053a6106d236600461557c565b611371565b61053a61150d565b60185461050f906001600160a01b031681565b61053a6107003660046151bd565b611531565b6104b96107133660046152ab565b61154c565b61053a61072636600461514a565b61155f565b61053a61073936600461567c565b61159b565b61053a61074c366004615184565b6115fd565b61055661075f36600461557c565b6118f3565b61058361077236600461557c565b611903565b61053a61078536600461570b565b61192e565b61053a6107983660046155f4565b611afa565b60865460ff166104b9565b61050f6107b636600461557c565b611b56565b6104ef611b61565b61053a6107d13660046156c2565b611bef565b6105836107e436600461514a565b611e2a565b61053a6107f736600461514a565b611e82565b61058360145481565b61053a6108133660046153ee565b611ece565b610583600f5481565b60035461050f906001600160a01b031681565b61053a6108423660046154e8565b612018565b61058361085536600461557c565b601b6020526000908152604090205481565b61053a612269565b61053a61087d36600461514a565b61228a565b61058360105481565b600d5461055690600160801b90046001600160401b031681565b600e5461055690600160401b90046001600160401b031681565b6104b96108cd366004615595565b60009182526022602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610583633b9aca0081565b610583600081565b61053a61091936600461527d565b6122fe565b61058361092c3660046152d7565b6123b3565b600d5461055690600160401b90046001600160401b031681565b61053a61095936600461531b565b61264a565b61053a61096c3660046156f0565b612721565b61053a61097f3660046151fe565b6127d5565b61058360015481565b61053a61099b3660046153ee565b612811565b600e54610556906001600160401b031681565b6105566109c136600461557c565b612e7f565b61053a6109d436600461570b565b612e8f565b6104ef6109e736600461557c565b612eea565b61058360165481565b610556610a0336600461557c565b613066565b61053a610a16366004615595565b613076565b600d54610556906001600160401b031681565b610556610a3c36600461557c565b61309c565b60065461050f906001600160a01b031681565b61058360175481565b610583670de0b6b3a764000081565b610a7f610a7a36600461567c565b6130ac565b604080519283526020830191909152016104c5565b61053a610aa2366004615595565b613102565b61053a610ab5366004615655565b6131b3565b6104b9610ac8366004615184565b6001600160a01b0391821660009081526020808052604080832093909416825291909152205460ff1690565b61058360135481565b610583610b0b36600461557c565b601c6020526000908152604090205481565b61053a610b2b36600461570b565b61335b565b60055461050f906001600160a01b031681565b610b78610b5136600461557c565b601a6020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080016104c5565b60006001600160e01b03198216636e44396d60e01b1480610bc957506001600160e01b03198216632303fc0360e01b145b80610be457506001600160e01b0319821663f7c618c160e01b145b80610bff57506001600160e01b0319821663aa283ab960e01b145b80610c1a57506001600160e01b03198216637965db0b60e01b145b80610c3557506001600160e01b03198216635b5e139f60e01b145b80610c5057506001600160e01b031982166380ac58cd60e01b145b80610c6b57506001600160e01b031982166301ffc9a760e01b145b92915050565b6000818152601d60205260408120546001600160a01b0316610cbe5760405162461bcd60e51b81526020600482015260016024820152601960f91b60448201526064015b60405180910390fd5b6000828152601f60205260409020546001600160a01b0316610c6b565b6000610ce682613482565b9050806001600160a01b0316836001600160a01b03161415610d2f5760405162461bcd60e51b8152602060048201526002602482015261333560f01b6044820152606401610cb5565b336001600160a01b0382161480610d6757506001600160a01b03811660009081526020808052604080832033845290915290205460ff165b610d835760405162461bcd60e51b8152600401610cb590615be3565b610d8d83836134d0565b505050565b6018546001600160a01b03163314610dbc5760405162461bcd60e51b8152600401610cb590615bc8565b6005546001600160a01b0384811691161415610dff5760405162461bcd60e51b8152602060048201526002602482015261032360f41b6044820152606401610cb5565b610e136001600160a01b038416838361353e565b816001600160a01b0316836001600160a01b03167ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b64883604051610e5891815260200190565b60405180910390a3505050565b600a8181548110610e7557600080fd5b9060005260206000209060049182820401919006600802915054906101000a90046001600160401b031681565b60865460ff1615610ec55760405162461bcd60e51b8152600401610cb590615b50565b3381610ed182826135a1565b610eed5760405162461bcd60e51b8152600401610cb590615be3565b6000838152601a602052604090208054600390910154610d8d918591610f139190615db5565b61361e565b3381610f2482826135a1565b610f405760405162461bcd60e51b8152600401610cb590615be3565b610f4b8585856136af565b5050505050565b60865460ff1615610f755760405162461bcd60e51b8152600401610cb590615b50565b6000828152601a6020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015290610fbc6137e6565b5090506000610fcc85848461386b565b91505080610f4b57600654600854610ff3916001600160a01b0391821691339116876138b2565b6000858152601a602052604081206002018054869290611014908490615c52565b925050819055507f10c4de39a7e804616cdc1b2dbf59fe6db0ed0d54ff69cef9c8fc024f79c7d47e8585856040015161104d9190615c52565b604080519283526020830191909152015b60405180910390a15050505050565b60008281526022602052604090206001015461108981336138f0565b610d8d8383613970565b6001600160a01b03811633146110d05760405162461bcd60e51b8152602060048201526002602482015261373160f01b6044820152606401610cb5565b6110da82826139f5565b5050565b600080516020615faa8339815191526110f781336138f0565b600e805467ffffffffffffffff60801b1916600160801b6001600160401b038516908102919091179091556040519081527f0cedd128b637e635da421319ae981d7968b7a477c1fa3b10275fac22ecbd51a6906020015b60405180910390a15050565b600080516020615faa83398151915261117381336138f0565b828280518251148015611187575060008251115b6111b75760405162461bcd60e51b81526020600482015260016024820152603560f81b6044820152606401610cb5565b60005b600182516111c89190615e03565b811161130557633b9aca006001600160401b03168282815181106111ee576111ee615f15565b60200260200101516001600160401b03161115801561123c5750633b9aca006001600160401b031683828151811061122857611228615f15565b60200260200101516001600160401b031611155b61126c5760405162461bcd60e51b81526020600482015260016024820152601b60f91b6044820152606401610cb5565b80156112f3578261127e600183615e03565b8151811061128e5761128e615f15565b60200260200101516001600160401b03168382815181106112b1576112b1615f15565b60200260200101516001600160401b0316116112f35760405162461bcd60e51b81526020600482015260016024820152603760f81b6044820152606401610cb5565b806112fd81615eba565b9150506111ba565b508451611319906011906020880190614f17565b50835161132d906012906020870190614f17565b507f275781d4ec4992e53f64326606b9f7eb81a89baf476df8de6d0410fd218e7be36011601260405161105e929190615b18565b60118181548110610e7557600080fd5b6018546001600160a01b0316331461139b5760405162461bcd60e51b8152600401610cb590615bc8565b6113a3613a78565b60175560135442106113c4576015546113bc9082615c95565b601455611406565b6000426013546113d49190615e03565b90506000601454826113e69190615db5565b6015549091506113f68285615c52565b6114009190615c95565b60145550505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561144a57600080fd5b505afa15801561145e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611482919061563c565b9050601554816114929190615c95565b60145411156114c85760405162461bcd60e51b8152602060048201526002602482015261191960f11b6044820152606401610cb5565b4260168190556015546114da91615c52565b6013556040518281527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9060200161114e565b600080516020615faa83398151915261152681336138f0565b61152e613ae0565b50565b610d8d838383604051806020016040528060008152506127d5565b600061155883836135a1565b9392505050565b600080516020615f8a83398151915261157881336138f0565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020615faa8339815191526115b481336138f0565b600f839055601082905560408051848152602081018490527fa0aa01eac9422dea36b84eb0bbc758e72643fbdbc72a4fd205d51c738803598291015b60405180910390a1505050565b602154610100900460ff1680611616575060215460ff16155b6116325760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015611654576021805461ffff19166101011790555b816001600160a01b03811661168f5760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b611697613b73565b61169f613bee565b600680546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a91600480820192602092909190829003018186803b1580156116f357600080fd5b505afa158015611707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172b9190615167565b600860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550836001600160a01b0316636ac5dc466040518163ffffffff1660e01b815260040160206040518083038186803b15801561178a57600080fd5b505afa15801561179e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c29190615167565b600780546001600160a01b03199081166001600160a01b0393841617909155600580549091168583161790556008546040805163313ce56760e01b81529051919092169163313ce567916004808301926020929190829003018186803b15801561182b57600080fd5b505afa15801561183f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611863919061573e565b61186e90600a615d0a565b60005560065461189690600080516020615f8a833981519152906001600160a01b0316613c4d565b6118bc600080516020615faa833981519152600080516020615f8a833981519152613c57565b6118d4600080516020615f8a83398151915280613c57565b6118dc613cab565b508015610d8d576021805461ff0019169055505050565b600b8181548110610e7557600080fd5b6000818152601a602052604081208054600390910154610c6b9184916119299190615db5565b613d03565b600080516020615faa83398151915261194781336138f0565b82633b9aca00816001600160401b031611156119895760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b82633b9aca00816001600160401b031611156119cb5760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b836001600160401b0316856001600160401b03161115611a115760405162461bcd60e51b81526020600482015260016024820152600760fb1b6044820152606401610cb5565b600d80546fffffffffffffffffffffffffffffffff16600160c01b6001600160401b038781169190910267ffffffffffffffff60801b191691909117600160801b91881691820217909155600754604051635b749f3560e01b815260048101929092526001600160a01b031690635b749f3590602401600060405180830381600087803b158015611aa157600080fd5b505af1158015611ab5573d6000803e3d6000fd5b5050604080516001600160401b03808a168252881660208201527f686faddec2d8b23f0f43c10006482b63941b927c9a98339cd78514b67139ad67935001905061105e565b600080516020615faa833981519152611b1381336138f0565b8151611b26906019906020850190614fcf565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad8260405161114e9190615b3d565b6000610c6b82613482565b60198054611b6e90615e85565b80601f0160208091040260200160405190810160405280929190818152602001828054611b9a90615e85565b8015611be75780601f10611bbc57610100808354040283529160200191611be7565b820191906000526020600020905b815481529060010190602001808311611bca57829003601f168201915b505050505081565b60865460ff1615611c125760405162461bcd60e51b8152600401610cb590615b50565b3383611c1e82826135a1565b611c3a5760405162461bcd60e51b8152600401610cb590615be3565b6000858152601a6020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015290611c816137e6565b509050600080611c9289858561386b565b915091508060001415611e1f57600e5460208501514291611cc491600160801b9091046001600160401b031690615c52565b11158015611cd157508188105b8015611ce05750836040015188105b8015611d255750600d54600160401b90046001600160401b0316611d048984615e03565b611d0e9190615db5565b633b9aca008560600151611d229190615db5565b11155b8015611d725750600d546040850151600160401b9091046001600160401b031690611d51908a90615e03565b611d5b9190615db5565b633b9aca008560600151611d6f9190615db5565b11155b611da35760405162461bcd60e51b8152602060048201526002602482015261333360f01b6044820152606401610cb5565b6000898152601a6020526040812060020180548a9290611dc4908490615e03565b925050819055507f10c4de39a7e804616cdc1b2dbf59fe6db0ed0d54ff69cef9c8fc024f79c7d47e89898660400151611dfd9190615e03565b6040805192835260208301919091520160405180910390a1611e1f8789613d67565b505050505050505050565b60006001600160a01b038216611e665760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b506001600160a01b03166000908152601e602052604090205490565b6007546001600160a01b03163314611eac5760405162461bcd60e51b8152600401610cb590615bc8565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60865460ff1615611ef15760405162461bcd60e51b8152600401610cb590615b50565b6000611efb6137e6565b5090506000805b8351811015611fd4576000848281518110611f1f57611f1f615f15565b60200260200101519050611f4a816000908152601d60205260409020546001600160a01b0316151590565b15611fc1576000818152601a602090815260408083208151608081018352815481526001820154938101939093526002810154918301919091526003015460608201529080611f9a84848961386b565b915091508060011415611fbd57611fb082613eb7565b611fba9087615c52565b95505b5050505b5080611fcc81615eba565b915050611f02565b5060408051338152602081018390527f4a9b62c74532d4448574775253ac495abc6f658b1284e9f28508a23135eeb641910160405180910390a1610d8d3382613d67565b600080516020615faa83398151915261203181336138f0565b838380518251148015612045575060008251115b6120755760405162461bcd60e51b81526020600482015260016024820152603560f81b6044820152606401610cb5565b60005b600182516120869190615e03565b81116121c357633b9aca006001600160401b03168282815181106120ac576120ac615f15565b60200260200101516001600160401b0316111580156120fa5750633b9aca006001600160401b03168382815181106120e6576120e6615f15565b60200260200101516001600160401b031611155b61212a5760405162461bcd60e51b81526020600482015260016024820152601b60f91b6044820152606401610cb5565b80156121b1578261213c600183615e03565b8151811061214c5761214c615f15565b60200260200101516001600160401b031683828151811061216f5761216f615f15565b60200260200101516001600160401b0316116121b15760405162461bcd60e51b81526020600482015260016024820152603760f81b6044820152606401610cb5565b806121bb81615eba565b915050612078565b508360ff16600114156121fd5785516121e3906009906020890190614f17565b5084516121f790600a906020880190614f17565b50612226565b855161221090600b906020890190614f17565b50845161222490600c906020880190614f17565b505b7f03c94e5b4f32a4b9a2709b098207aebe4cc92c950987ee077776cc2300adcde286868660405161225993929190615adf565b60405180910390a1505050505050565b600080516020615faa83398151915261228281336138f0565b61152e613cab565b6018546001600160a01b031633146122b45760405162461bcd60e51b8152600401610cb590615bc8565b601880546001600160a01b0319166001600160a01b0383169081179091556040517f1c794a043683a294127c95bc365bae91b63b651eb9884a2c9120afee2bb690b490600090a250565b6001600160a01b03821633141561233c5760405162461bcd60e51b8152602060048201526002602482015261199b60f11b6044820152606401610cb5565b336000818152602080805260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516123a7911515815260200190565b60405180910390a35050565b60006123c160865460ff1690565b156123de5760405162461bcd60e51b8152600401610cb590615b50565b856001600160a01b0381166124195760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b6000851161244e5760405162461bcd60e51b8152602060048201526002602482015261323760f01b6044820152606401610cb5565b60065460085461246d916001600160a01b0391821691339116896138b2565b60006124776137e6565b915050848111156124af5760405162461bcd60e51b8152602060048201526002602482015261064760f31b6044820152606401610cb5565b600080546124bd8389615db5565b6124c79190615c95565b905060006124d689838a613efa565b90508581101561250d5760405162461bcd60e51b8152602060048201526002602482015261323960f01b6044820152606401610cb5565b600d5461252b908290600160401b90046001600160401b0316615db5565b612539633b9aca008a615db5565b111561256c5760405162461bcd60e51b8152602060048201526002602482015261033360f41b6044820152606401610cb5565b61257a600280546001019055565b600254945061258a8560006140b0565b816001600082825461259c9190615c52565b909155505060408051608081018252848152426020808301918252828401858152606084018d815260008b8152601a90935294909120925183559051600183015551600282015590516003909101556125f58a866140f6565b6040805186815260208101859052908101829052606081018990527f2af29ed8e180e9bfa65515c22e3af766d15e852ec59b9666d6eeaef8a97565929060800160405180910390a15050505095945050505050565b600080516020615f8a83398151915261266381336138f0565b60005b85518110156126b2576126a0600080516020615faa83398151915287838151811061269357612693615f15565b6020026020010151613970565b806126aa81615eba565b915050612666565b506126cb600080516020615faa83398151915285613970565b6007546126f090600080516020615faa833981519152906001600160a01b0316613970565b50600480546001600160a01b039384166001600160a01b031991821617909155600380549290931691161790555050565b600080516020615faa83398151915261273a81336138f0565b81633b9aca00816001600160401b0316111561277c5760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b600e80546001600160c01b0316600160c01b6001600160401b038681168202929092179283905560405192041681527f264a4c2e5ed86659859b3c52d1b00a899950c0f3a637d68ca438cc0216dd89bf906020016115f0565b33826127e182826135a1565b6127fd5760405162461bcd60e51b8152600401610cb590615be3565b612809868686866141c6565b505050505050565b60865460ff16156128345760405162461bcd60e51b8152600401610cb590615b50565b60008061283f6137e6565b915091506000600760009054906101000a90046001600160a01b03166001600160a01b031663344844db6040518163ffffffff1660e01b815260040160206040518083038186803b15801561289357600080fd5b505afa1580156128a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cb919061563c565b600d54909150600090633b9aca00906128f490600160801b90046001600160401b031684615db5565b6128fe9190615c95565b600d54909150633b9aca009061292490600160c01b90046001600160401b031684615db5565b61292e9190615c95565b600154116129635760405162461bcd60e51b81526020600482015260026024820152610ccd60f21b6044820152606401610cb5565b600080600087516001600160401b0381111561298157612981615f2b565b6040519080825280602002602001820160405280156129c657816020015b604080518082019091526000808252602082015281526020019060019003908161299f5790505b50905060005b8851811015612b825760008982815181106129e9576129e9615f15565b6020908102919091018101516000818152601d9092526040909120549091506001600160a01b03168015612b6d576000828152601a602090815260408083208151608081018352815481526001820154938101939093526002810154918301919091526003015460608201529080612a6285848f61386b565b915091508060011415612a8957612a7882613eb7565b612a82908a615c52565b9850612b56565b600e5460208401514291612aae91600160801b9091046001600160401b031690615c52565b11612b5657612abd858461420e565b60006001548b1115612aed578a633b9aca00600154612adc9190615db5565b612ae69190615c95565b9050612af4565b50633b9aca005b600080612b0685876060015185614269565b9092509050612b15818c615c52565b9a506040518060400160405280886001600160a01b03168152602001838152508a8a81518110612b4757612b47615f15565b60200260200101819052505050505b8960015411612b69575050505050612b82565b5050505b50508080612b7a90615eba565b9150506129cc565b5060008415612bb757612b96856002615db5565b633b9aca00600154612ba89190615db5565b612bb29190615c95565b612bba565b60005b9050633b9aca00612cd0826011805480602002602001604051908101604052809291908181526020018280548015612c4357602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411612c005790505b50505050506012805480602002602001604051908101604052809291908181526020018280548015612cc657602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411612c835790505b50505050506143dd565b612ce3906001600160401b031685615db5565b612ced9190615c95565b92506010548310612d0057601054612d02565b825b92506000633b9aca00612d1789612710615db5565b612d219190615db5565b600054600d548990612d4c906001600160401b03600160801b8204811691600160c01b900416615e1a565b612d57906005615dd4565b6001600160401b0316612d6a9190615db5565b612d749190615db5565b612d7e9190615c95565b9050808410612d8d5780612d8f565b835b93507fb789efbabfeba5ae006c34c3b3c17f6b1cf34ab2ac684be93d1e64da000b5be78a8433612dbf8989615c52565b604051612dcf9493929190615a33565b60405180910390a160005b8a51811015612e5f576000848281518110612df757612df7615f15565b6020026020010151602001511115612e4d57612e4d848281518110612e1e57612e1e615f15565b602002602001015160000151858381518110612e3c57612e3c615f15565b602002602001015160200151613d67565b80612e5781615eba565b915050612dda565b50612e7333612e6e8787615c52565b613d67565b50505050505050505050565b60098181548110610e7557600080fd5b6004546001600160a01b03163314612eb95760405162461bcd60e51b8152600401610cb590615bc8565b600e80546001600160401b03928316600160401b026001600160801b03199091169290931691909117919091179055565b6000818152601d60205260409020546060906001600160a01b0316612f355760405162461bcd60e51b81526020600482015260016024820152601960f91b6044820152606401610cb5565b8160005b8115612f5f5780612f4981615eba565b9150612f589050600a83615c95565b9150612f39565b6000816001600160401b03811115612f7957612f79615f2b565b6040519080825280601f01601f191660200182016040528015612fa3576020820181803683370190505b5090505b841561300e57612fb8600183615e03565b9150612fc5600a86615ed5565b612fd0906030615c52565b60f81b818381518110612fe557612fe5615f15565b60200101906001600160f81b031916908160001a905350613007600a86615c95565b9450612fa7565b60006019805461301d90615e85565b905011613039576040518060200160405280600081525061305d565b60198160405160200161304d9291906158ee565b6040516020818303038152906040525b95945050505050565b60128181548110610e7557600080fd5b60008281526022602052604090206001015461309281336138f0565b610d8d83836139f5565b600c8181548110610e7557600080fd5b6000828152601a6020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015281906130f68185614726565b92509250509250929050565b600080516020615faa83398151915261311b81336138f0565b816001600160a01b0381166131565760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b6015849055601880546001600160a01b0319166001600160a01b0385169081179091556040518581527fe139be2fc520b685c93d718b643b5d8c42fc57b5724201180c5d765635467312906020015b60405180910390a250505050565b60865460ff16156131d65760405162461bcd60e51b8152600401610cb590615b50565b33836131e282826135a1565b6131fe5760405162461bcd60e51b8152600401610cb590615be3565b6000858152601a60209081526040808320815160808101835281548152600182015493810193909352600281015491830191909152600301546060820152906132456137e6565b50905060008061325689858561386b565b915091508060001415611e1f57600e546020850151429161328891600160801b9091046001600160401b031690615c52565b11156132bb5760405162461bcd60e51b8152602060048201526002602482015261333160f01b6044820152606401610cb5565b6132c5898561420e565b60006132e08386606001516132db6001546147ce565b614269565b509050878110156133185760405162461bcd60e51b8152602060048201526002602482015261199960f11b6044820152606401610cb5565b604080518b8152602081018390527f2f06d076c30d294b959d7aa34f40d448e45f487492a47889f02831bb06fee6bf910160405180910390a1612e738982613d67565b600080516020615faa83398151915261337481336138f0565b81633b9aca00816001600160401b031611156133b65760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b6133c08385615dd4565b6001600160401b03166133d86002633b9aca00615d0a565b116134095760405162461bcd60e51b81526020600482015260016024820152600760fb1b6044820152606401610cb5565b600d80546001600160801b031916600160401b6001600160401b0387811691820267ffffffffffffffff1916929092179186169182179092556040805192835260208301919091527fb556fe5cb4a1a8243b8d5000bbefd6f8b868adcac2765cd4a30ac9320ff1a0b6910160405180910390a150505050565b6000818152601d60205260409020546001600160a01b0316806134cb5760405162461bcd60e51b81526020600482015260016024820152601960f91b6044820152606401610cb5565b919050565b6000818152601f6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061350582613482565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6040516001600160a01b038316602482015260448101829052610d8d90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148c7565b6000806135ad83613482565b9050806001600160a01b0316846001600160a01b031614806135e857506000838152601f60205260409020546001600160a01b038581169116145b8061361657506001600160a01b038082166000908152602080805260408083209388168352929052205460ff165b949350505050565b61362882826140b0565b6000828152601c60205260409020548015610d8d576000838152601c60209081526040808320839055601d9091529020546005546001600160a01b03918216916136749116828461353e565b806001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486836040516131a591815260200190565b826001600160a01b03166136c282613482565b6001600160a01b0316146136e85760405162461bcd60e51b8152600401610cb590615bc8565b6001600160a01b0382166137235760405162461bcd60e51b8152602060048201526002602482015261191b60f11b6044820152606401610cb5565b61372e6000826134d0565b6001600160a01b0383166000908152601e60205260408120805460019290613757908490615e03565b90915550506001600160a01b0382166000908152601e60205260408120805460019290613785908490615c52565b90915550506000818152601d602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600354604080516341f654f760e01b8152815160009384936001600160a01b03909116926341f654f79260048083019392829003018186803b15801561382b57600080fd5b505afa15801561383f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613863919061569e565b915091509091565b600080600080600061387d8787614726565b9150915081600014806138905750806001145b156138a45761389f888861420e565b600192505b50925090505b935093915050565b6040516001600160a01b03808516602483015283166044820152606481018290526138ea9085906323b872dd60e01b9060840161356a565b50505050565b60008281526022602090815260408083206001600160a01b038516845290915290205460ff166110da5761392e816001600160a01b03166014614999565b613939836020614999565b60405160200161394a92919061598c565b60408051601f198184030181529082905262461bcd60e51b8252610cb591600401615b3d565b60008281526022602090815260408083206001600160a01b038516845290915290205460ff166110da5760008281526022602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60008281526022602090815260408083206001600160a01b038516845290915290205460ff16156110da5760008281526022602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600060015460001415613a8c575060175490565b600154670de0b6b3a7640000601454601654613aa6614b34565b613ab09190615e03565b613aba9190615db5565b613ac49190615db5565b613ace9190615c95565b601754613adb9190615c52565b905090565b60865460ff16613b295760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610cb5565b6086805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b602154610100900460ff1680613b8c575060215460ff16155b613ba85760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015613bca576021805461ffff19166101011790555b613bd2614b4f565b613bda614bb9565b801561152e576021805461ff001916905550565b602154610100900460ff1680613c07575060215460ff16155b613c235760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015613c45576021805461ffff19166101011790555b613bda614b4f565b6110da8282613970565b600082815260226020526040902060010154819060405184907fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff90600090a460009182526022602052604090912060010155565b60865460ff1615613cce5760405162461bcd60e51b8152600401610cb590615b50565b6086805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613b563390565b6000828152601c60209081526040808320548354601b90935290832054909190670de0b6b3a764000090613d35613a78565b613d3f9190615e03565b613d499086615db5565b613d539190615c95565b613d5d9190615c95565b6115589190615c52565b60065460408051629032ff60e51b815290516000926001600160a01b0316916312065fe0916004808301926020929190829003018186803b158015613dab57600080fd5b505afa158015613dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613de3919061563c565b9050818110158015613df55750600082115b15613e1857600654600854610d8d916001600160a01b03918216911685856138b2565b8115610d8d576000613e2a8284615e03565b600654600854919250613e4b916001600160a01b03908116911686856138b2565b600754604051631a115ff160e01b8152600481018390526001600160a01b03868116602483015290911690631a115ff190604401600060405180830381600087803b158015613e9957600080fd5b505af1158015613ead573d6000803e3d6000fd5b5050505050505050565b600e54600090633b9aca0090613edd90600160c01b90046001600160401b031684615db5565b613ee79190615c95565b9050600f5481106134cb57600f54610c6b565b600080613f1384600154613f0e9190615c52565b6147ce565b9050633b9aca006001600160401b03821610613f565760405162461bcd60e51b8152602060048201526002602482015261323560f01b6044820152606401610cb5565b6000633b9aca00614042836009805480602002602001604051908101604052809291908181526020018280548015613fdf57602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411613f9c5790505b5050505050600a805480602002602001604051908101604052809291908181526020018280548015612cc657600091825260209182902080546001600160401b03168452908202830192909160089101808411612c8357905050505050506143dd565b600e5461405891906001600160401b0316615dd4565b6001600160401b031661406b9190615c95565b9050633b9aca0061407c8282615e03565b6140869086615db5565b6140909190615c95565b61409a9085615e03565b90506140a68187615e03565b9695505050505050565b6140b8613a78565b6017556140c3614b34565b6016556140d08282613d03565b6000928352601c6020908152604080852092909255601754601b90915292209190915550565b6001600160a01b0382166000908152601e6020526040812080546001929061411f908490615c52565b90915550506000818152601d602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46141956000838360405180602001604052806000815250614c2e565b6110da5760405162461bcd60e51b81526020600482015260026024820152610c8d60f21b6044820152606401610cb5565b6141d18484846136af565b6141dd84848484614c2e565b6138ea5760405162461bcd60e51b81526020600482015260026024820152610c8d60f21b6044820152606401610cb5565b8051606082015160009161422191615db5565b905061422d838261361e565b6000838152601b60205260408120819055546142499082615c95565b6001600082825461425a9190615e03565b90915550610d8d905083614d50565b600080633b9aca0061435684600b8054806020026020016040519081016040528092919081815260200182805480156142f357602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b0316815260200190600801906020826007010492830192600103820291508084116142b05790505b5050505050600c805480602002602001604051908101604052809291908181526020018280548015612cc657600091825260209182902080546001600160401b03168452908202830192909160089101808411612c8357905050505050506143dd565b600e546143739190600160401b90046001600160401b0316615dd4565b6001600160401b03166143869190615c95565b9050633b9aca006143978282615e03565b6143a19086615db5565b6143ab9190615c95565b6143b59085615e03565b90508481106143c9575060009050836138aa565b6143d38186615e03565b9150935093915050565b600082600184516143ee9190615e03565b815181106143fe576143fe615f15565b60200260200101516001600160401b0316846001600160401b03161061444c57816001845161442d9190615e03565b8151811061443d5761443d615f15565b60200260200101519050611558565b8260008151811061445f5761445f615f15565b60200260200101516001600160401b0316846001600160401b031611614492578160008151811061443d5761443d615f15565b600080600185516144a39190615e03565b905060005b60016144b48484615e03565b111561451e5760026144c68484615e03565b6144d09190615c95565b6144da9084615c52565b9050866001600160401b03168682815181106144f8576144f8615f15565b60200260200101516001600160401b031611614516578092506144a8565b8091506144a8565b84838151811061453057614530615f15565b60200260200101516001600160401b031685838151811061455357614553615f15565b60200260200101516001600160401b0316111561464d5785838151811061457c5761457c615f15565b602002602001015186838151811061459657614596615f15565b60200260200101516145a89190615e1a565b8684815181106145ba576145ba615f15565b6020026020010151886145cd9190615e1a565b8685815181106145df576145df615f15565b60200260200101518785815181106145f9576145f9615f15565b602002602001015161460b9190615e1a565b6146159190615dd4565b61461f9190615ca9565b85848151811061463157614631615f15565b60200260200101516146439190615c6a565b9350505050611558565b85838151811061465f5761465f615f15565b602002602001015186838151811061467957614679615f15565b602002602001015161468b9190615e1a565b86848151811061469d5761469d615f15565b6020026020010151886146b09190615e1a565b8684815181106146c2576146c2615f15565b60200260200101518786815181106146dc576146dc615f15565b60200260200101516146ee9190615e1a565b6146f89190615dd4565b6147029190615ca9565b85848151811061471457614714615f15565b60200260200101516146439190615e1a565b600080600083856000015186606001516147409190615db5565b61474a9190615c95565b9050846040015185606001516147609190615c52565b811061476f57600092506147c6565b80856040015186606001516147849190615c52565b61478e9190615e03565b600d5460608701519194506147ae916001600160401b0390911690615db5565b6147bc633b9aca0085615db5565b116147c657600191505b509250929050565b600080633b9aca00600d60109054906101000a90046001600160401b03166001600160401b0316600760009054906101000a90046001600160a01b03166001600160a01b031663344844db6040518163ffffffff1660e01b815260040160206040518083038186803b15801561484357600080fd5b505afa158015614857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061487b919061563c565b6148859190615db5565b61488f9190615c95565b9050808310156148b957806148a8633b9aca0085615db5565b6148b29190615c95565b91506148c1565b633b9aca0091505b50919050565b600061491c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614e0c9092919063ffffffff16565b805190915015610d8d578080602001905181019061493a919061555f565b610d8d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cb5565b606060006149a8836002615db5565b6149b3906002615c52565b6001600160401b038111156149ca576149ca615f2b565b6040519080825280601f01601f1916602001820160405280156149f4576020820181803683370190505b509050600360fc1b81600081518110614a0f57614a0f615f15565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614a3e57614a3e615f15565b60200101906001600160f81b031916908160001a9053506000614a62846002615db5565b614a6d906001615c52565b90505b6001811115614ae5576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614aa157614aa1615f15565b1a60f81b828281518110614ab757614ab7615f15565b60200101906001600160f81b031916908160001a90535060049490941c93614ade81615e6e565b9050614a70565b5083156115585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610cb5565b6000806013544210614b4857601354610c6b565b4292915050565b602154610100900460ff1680614b68575060215460ff16155b614b845760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015613bda576021805461ffff1916610101179055801561152e576021805461ff001916905550565b602154610100900460ff1680614bd2575060215460ff16155b614bee5760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015614c10576021805461ffff19166101011790555b6086805460ff19169055801561152e576021805461ff001916905550565b60006001600160a01b0384163b15614d4557604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614c72903390899088908890600401615a01565b602060405180830381600087803b158015614c8c57600080fd5b505af1925050508015614cbc575060408051601f3d908101601f19168201909252614cb9918101906155d7565b60015b614d2b573d808015614cea576040519150601f19603f3d011682016040523d82523d6000602084013e614cef565b606091505b508051614d235760405162461bcd60e51b81526020600482015260026024820152610c8d60f21b6044820152606401610cb5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613616565b506001949350505050565b6000614d5b82613482565b9050614d686000836134d0565b6001600160a01b0381166000908152601e60205260408120805460019290614d91908490615e03565b90915550506000828152601d6020908152604080832080546001600160a01b0319169055601a9091528082208281556001810183905560028101839055600301829055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6060613616848460008585843b614e655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cb5565b600080866001600160a01b03168587604051614e8191906158d2565b60006040518083038185875af1925050503d8060008114614ebe576040519150601f19603f3d011682016040523d82523d6000602084013e614ec3565b606091505b5091509150614ed3828286614ede565b979650505050505050565b60608315614eed575081611558565b825115614efd5782518084602001fd5b8160405162461bcd60e51b8152600401610cb59190615b3d565b82805482825590600052602060002090600301600490048101928215614fbf5791602002820160005b83821115614f8a57835183826101000a8154816001600160401b0302191690836001600160401b031602179055509260200192600801602081600701049283019260010302614f40565b8015614fbd5782816101000a8154906001600160401b030219169055600801602081600701049283019260010302614f8a565b505b50614fcb929150615043565b5090565b828054614fdb90615e85565b90600052602060002090601f016020900481019282614ffd5760008555614fbf565b82601f1061501657805160ff1916838001178555614fbf565b82800160010185558215614fbf579182015b82811115614fbf578251825591602001919060010190615028565b5b80821115614fcb5760008155600101615044565b60006001600160401b0383111561507157615071615f2b565b615084601f8401601f1916602001615bff565b905082815283838301111561509857600080fd5b828260208301376000602084830101529392505050565b80356134cb81615f41565b600082601f8301126150cb57600080fd5b813560206150e06150db83615c2f565b615bff565b80838252828201915082860187848660051b890101111561510057600080fd5b60005b858110156151265761511482615133565b84529284019290840190600101615103565b5090979650505050505050565b80356001600160401b03811681146134cb57600080fd5b60006020828403121561515c57600080fd5b813561155881615f41565b60006020828403121561517957600080fd5b815161155881615f41565b6000806040838503121561519757600080fd5b82356151a281615f41565b915060208301356151b281615f41565b809150509250929050565b6000806000606084860312156151d257600080fd5b83356151dd81615f41565b925060208401356151ed81615f41565b929592945050506040919091013590565b6000806000806080858703121561521457600080fd5b843561521f81615f41565b9350602085013561522f81615f41565b92506040850135915060608501356001600160401b0381111561525157600080fd5b8501601f8101871361526257600080fd5b61527187823560208401615058565b91505092959194509250565b6000806040838503121561529057600080fd5b823561529b81615f41565b915060208301356151b281615f56565b600080604083850312156152be57600080fd5b82356152c981615f41565b946020939093013593505050565b600080600080600060a086880312156152ef57600080fd5b85356152fa81615f41565b97602087013597506040870135966060810135965060800135945092505050565b6000806000806080858703121561533157600080fd5b84356001600160401b0381111561534757600080fd5b8501601f8101871361535857600080fd5b803560206153686150db83615c2f565b8083825282820191508285018b848660051b880101111561538857600080fd5b600095505b848610156153b45780356153a081615f41565b83526001959095019491830191830161538d565b5097506153c490508882016150af565b95505050506153d5604086016150af565b91506153e3606086016150af565b905092959194509250565b6000602080838503121561540157600080fd5b82356001600160401b0381111561541757600080fd5b8301601f8101851361542857600080fd5b80356154366150db82615c2f565b80828252848201915084840188868560051b870101111561545657600080fd5b600094505b8385101561547957803583526001949094019391850191850161545b565b50979650505050505050565b6000806040838503121561549857600080fd5b82356001600160401b03808211156154af57600080fd5b6154bb868387016150ba565b935060208501359150808211156154d157600080fd5b506154de858286016150ba565b9150509250929050565b6000806000606084860312156154fd57600080fd5b83356001600160401b038082111561551457600080fd5b615520878388016150ba565b9450602086013591508082111561553657600080fd5b50615543868287016150ba565b925050604084013561555481615f7a565b809150509250925092565b60006020828403121561557157600080fd5b815161155881615f56565b60006020828403121561558e57600080fd5b5035919050565b600080604083850312156155a857600080fd5b8235915060208301356151b281615f41565b6000602082840312156155cc57600080fd5b813561155881615f64565b6000602082840312156155e957600080fd5b815161155881615f64565b60006020828403121561560657600080fd5b81356001600160401b0381111561561c57600080fd5b8201601f8101841361562d57600080fd5b61361684823560208401615058565b60006020828403121561564e57600080fd5b5051919050565b60008060006060848603121561566a57600080fd5b8335925060208401356151ed81615f41565b6000806040838503121561568f57600080fd5b50508035926020909101359150565b600080604083850312156156b157600080fd5b505080516020909101519092909150565b6000806000606084860312156156d757600080fd5b8335925060208401359150604084013561555481615f41565b60006020828403121561570257600080fd5b61155882615133565b6000806040838503121561571e57600080fd5b61572783615133565b915061573560208401615133565b90509250929050565b60006020828403121561575057600080fd5b815161155881615f7a565b600081518084526020808501945080840160005b838110156157945781516001600160401b03168752958201959082019060010161576f565b509495945050505050565b805480835260008281526020808220940193909190825b826003820110156158055781546001600160401b038082168852604082811c821660208a0152608083811c9092169089015260c09190911c6060880152909501946001909101906004016157b6565b90549082811015615826576001600160401b03821686526020909501946001015b82811015615848576001600160401b03604083901c1686526020909501946001015b8281101561586a576001600160401b03608083901c1686526020909501946001015b828110156158805760c082901c86526020860195505b5093949350505050565b600081518084526158a2816020860160208601615e42565b601f01601f19169290920160200192915050565b600081516158c8818560208601615e42565b9290920192915050565b600082516158e4818460208701615e42565b9190910192915050565b600080845481600182811c91508083168061590a57607f831692505b602080841082141561592a57634e487b7160e01b86526022600452602486fd5b81801561593e576001811461594f5761597c565b60ff1986168952848901965061597c565b60008b81526020902060005b868110156159745781548b82015290850190830161595b565b505084890196505b50505050505061305d81856158b6565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516159c4816017850160208801615e42565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516159f5816028840160208801615e42565b01602801949350505050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526140a6608083018461588a565b6080808252855190820181905260009060209060a0840190828901845b82811015615a6c57815184529284019290840190600101615a50565b5050508381038285015286518082528783019183019060005b81811015615ab557835180516001600160a01b031684528501518584015292840192604090920191600101615a85565b50506001600160a01b03871660408601529250615ad0915050565b82606083015295945050505050565b606081526000615af2606083018661575b565b8281036020840152615b04818661575b565b91505060ff83166040830152949350505050565b604081526000615b2b604083018561579f565b828103602084015261305d818561579f565b602081526000611558602083018461588a565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252600190820152603160f81b604082015260600190565b602080825260029082015261323160f01b604082015260600190565b604051601f8201601f191681016001600160401b0381118282101715615c2757615c27615f2b565b604052919050565b60006001600160401b03821115615c4857615c48615f2b565b5060051b60200190565b60008219821115615c6557615c65615ee9565b500190565b60006001600160401b03808316818516808303821115615c8c57615c8c615ee9565b01949350505050565b600082615ca457615ca4615eff565b500490565b60006001600160401b0380841680615cc357615cc3615eff565b92169190910492915050565b600181815b808511156147c6578160001904821115615cf057615cf0615ee9565b80851615615cfd57918102915b93841c9390800290615cd4565b600061155860ff841683600082615d2357506001610c6b565b81615d3057506000610c6b565b8160018114615d465760028114615d5057615d6c565b6001915050610c6b565b60ff841115615d6157615d61615ee9565b50506001821b610c6b565b5060208310610133831016604e8410600b8410161715615d8f575081810a610c6b565b615d998383615ccf565b8060001904821115615dad57615dad615ee9565b029392505050565b6000816000190483118215151615615dcf57615dcf615ee9565b500290565b60006001600160401b0380831681851681830481118215151615615dfa57615dfa615ee9565b02949350505050565b600082821015615e1557615e15615ee9565b500390565b60006001600160401b0383811690831681811015615e3a57615e3a615ee9565b039392505050565b60005b83811015615e5d578181015183820152602001615e45565b838111156138ea5750506000910152565b600081615e7d57615e7d615ee9565b506000190190565b600181811c90821680615e9957607f821691505b602082108114156148c157634e487b7160e01b600052602260045260246000fd5b6000600019821415615ece57615ece615ee9565b5060010190565b600082615ee457615ee4615eff565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461152e57600080fd5b801515811461152e57600080fd5b6001600160e01b03198116811461152e57600080fd5b60ff8116811461152e57600080fdfe5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56255435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041a264697066735822122045840058006f230868797238b1a0691e6a0b163718211cd780d1fcfd01a5532c64736f6c63430008070033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106104a15760003560e01c80637bd06a151161026d578063c0212c7211610151578063df136d65116100ce578063e985e9c511610092578063e985e9c514610aba578063ebe2b12b14610af4578063f301af4214610afd578063f5d011c514610b1d578063f7c618c114610b30578063f902fad714610b4357600080fd5b8063df136d6514610a54578063df1b8bd314610a5d578063e048684214610a6c578063e2b01a5e14610a94578063e5234c7a14610aa757600080fd5b8063d1aace9f11610115578063d1aace9f146109f5578063d547741f14610a08578063d5eb058114610a1b578063d7f6328e14610a2e578063dc4c90d314610a4157600080fd5b8063c0212c72146109a0578063c1618dda146109b3578063c628a6f7146109c6578063c87b56dd146109d9578063c8f33c91146109ec57600080fd5b806395d89b41116101ea578063ae3302c2116101ae578063ae3302c214610931578063b126e7e51461094b578063b3b1cb271461095e578063b88d4fde14610971578063b8f3689514610984578063bcb01a801461098d57600080fd5b806395d89b41146104ce5780639f48118f146108f8578063a217fddf14610903578063a22cb4651461090b578063a62b2a3d1461091e57600080fd5b8063873291bb11610231578063873291bb1461086f5780638c6dfaf7146108825780638d5e19f11461088b5780638e240144146108a557806391d14854146108bf57600080fd5b80637bd06a15146108185780637dc0d1d0146108215780638211477a14610834578063840a7698146108475780638456cb591461086757600080fd5b8063386a9525116103945780634d6ed8c4116103115780636c0360eb116102d55780636c0360eb146107bb5780636d59dae7146107c357806370a08231146107d65780637adbf973146107e95780637b0a47ee146107fc5780637b39ecf71461080557600080fd5b80634d6ed8c414610764578063515dc4801461077757806355f804b31461078a5780635c975abb1461079d5780636352211e146107a857600080fd5b8063430c208111610358578063430c208114610705578063472d35b91461071857806347c12e011461072b578063485cc9551461073e57806349a5d3ef1461075157600080fd5b8063386a9525146106bb5780633c6b16ab146106c45780633f4ba83a146106d75780633fc6df6e146106df57806342842e0e146106f257600080fd5b806323b872dd11610422578063324f3815116103e6578063324f38151461065557806336568abe1461066f5780633675441514610682578063367f21b41461069557806338050129146106a857600080fd5b806323b872dd146105e4578063248a9ca3146105f757806324d83b791461061a57806324ea54f41461062d5780632f2ff15d1461064257600080fd5b80630c016dc0116104695780630c016dc01461056e5780630d668087146105915780631171bda9146105ab578063142c3ba0146105be5780631c4b774b146105d157600080fd5b806301ffc9a7146104a657806306fdde03146104ce578063081812fc146104fc578063095ea7b3146105275780630bfab8a71461053c575b600080fd5b6104b96104b43660046155ba565b610b98565b60405190151581526020015b60405180910390f35b6040805180820190915260098152680416e676c65506572760bc1b60208201525b6040516104c59190615b3d565b61050f61050a36600461557c565b610c71565b6040516001600160a01b0390911681526020016104c5565b61053a6105353660046152ab565b610cdb565b005b600e5461055690600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020016104c5565b610583600080516020615f8a83398151915281565b6040519081526020016104c5565b600e5461055690600160801b90046001600160401b031681565b61053a6105b93660046151bd565b610d92565b6105566105cc36600461557c565b610e65565b61053a6105df36600461557c565b610ea2565b61053a6105f23660046151bd565b610f18565b61058361060536600461557c565b60009081526022602052604090206001015490565b61053a61062836600461567c565b610f52565b610583600080516020615faa83398151915281565b61053a610650366004615595565b61106d565b600d5461055690600160c01b90046001600160401b031681565b61053a61067d366004615595565b611093565b61053a6106903660046156f0565b6110de565b61053a6106a3366004615485565b61115a565b6105566106b636600461557c565b611361565b61058360155481565b61053a6106d236600461557c565b611371565b61053a61150d565b60185461050f906001600160a01b031681565b61053a6107003660046151bd565b611531565b6104b96107133660046152ab565b61154c565b61053a61072636600461514a565b61155f565b61053a61073936600461567c565b61159b565b61053a61074c366004615184565b6115fd565b61055661075f36600461557c565b6118f3565b61058361077236600461557c565b611903565b61053a61078536600461570b565b61192e565b61053a6107983660046155f4565b611afa565b60865460ff166104b9565b61050f6107b636600461557c565b611b56565b6104ef611b61565b61053a6107d13660046156c2565b611bef565b6105836107e436600461514a565b611e2a565b61053a6107f736600461514a565b611e82565b61058360145481565b61053a6108133660046153ee565b611ece565b610583600f5481565b60035461050f906001600160a01b031681565b61053a6108423660046154e8565b612018565b61058361085536600461557c565b601b6020526000908152604090205481565b61053a612269565b61053a61087d36600461514a565b61228a565b61058360105481565b600d5461055690600160801b90046001600160401b031681565b600e5461055690600160401b90046001600160401b031681565b6104b96108cd366004615595565b60009182526022602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610583633b9aca0081565b610583600081565b61053a61091936600461527d565b6122fe565b61058361092c3660046152d7565b6123b3565b600d5461055690600160401b90046001600160401b031681565b61053a61095936600461531b565b61264a565b61053a61096c3660046156f0565b612721565b61053a61097f3660046151fe565b6127d5565b61058360015481565b61053a61099b3660046153ee565b612811565b600e54610556906001600160401b031681565b6105566109c136600461557c565b612e7f565b61053a6109d436600461570b565b612e8f565b6104ef6109e736600461557c565b612eea565b61058360165481565b610556610a0336600461557c565b613066565b61053a610a16366004615595565b613076565b600d54610556906001600160401b031681565b610556610a3c36600461557c565b61309c565b60065461050f906001600160a01b031681565b61058360175481565b610583670de0b6b3a764000081565b610a7f610a7a36600461567c565b6130ac565b604080519283526020830191909152016104c5565b61053a610aa2366004615595565b613102565b61053a610ab5366004615655565b6131b3565b6104b9610ac8366004615184565b6001600160a01b0391821660009081526020808052604080832093909416825291909152205460ff1690565b61058360135481565b610583610b0b36600461557c565b601c6020526000908152604090205481565b61053a610b2b36600461570b565b61335b565b60055461050f906001600160a01b031681565b610b78610b5136600461557c565b601a6020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080016104c5565b60006001600160e01b03198216636e44396d60e01b1480610bc957506001600160e01b03198216632303fc0360e01b145b80610be457506001600160e01b0319821663f7c618c160e01b145b80610bff57506001600160e01b0319821663aa283ab960e01b145b80610c1a57506001600160e01b03198216637965db0b60e01b145b80610c3557506001600160e01b03198216635b5e139f60e01b145b80610c5057506001600160e01b031982166380ac58cd60e01b145b80610c6b57506001600160e01b031982166301ffc9a760e01b145b92915050565b6000818152601d60205260408120546001600160a01b0316610cbe5760405162461bcd60e51b81526020600482015260016024820152601960f91b60448201526064015b60405180910390fd5b6000828152601f60205260409020546001600160a01b0316610c6b565b6000610ce682613482565b9050806001600160a01b0316836001600160a01b03161415610d2f5760405162461bcd60e51b8152602060048201526002602482015261333560f01b6044820152606401610cb5565b336001600160a01b0382161480610d6757506001600160a01b03811660009081526020808052604080832033845290915290205460ff165b610d835760405162461bcd60e51b8152600401610cb590615be3565b610d8d83836134d0565b505050565b6018546001600160a01b03163314610dbc5760405162461bcd60e51b8152600401610cb590615bc8565b6005546001600160a01b0384811691161415610dff5760405162461bcd60e51b8152602060048201526002602482015261032360f41b6044820152606401610cb5565b610e136001600160a01b038416838361353e565b816001600160a01b0316836001600160a01b03167ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b64883604051610e5891815260200190565b60405180910390a3505050565b600a8181548110610e7557600080fd5b9060005260206000209060049182820401919006600802915054906101000a90046001600160401b031681565b60865460ff1615610ec55760405162461bcd60e51b8152600401610cb590615b50565b3381610ed182826135a1565b610eed5760405162461bcd60e51b8152600401610cb590615be3565b6000838152601a602052604090208054600390910154610d8d918591610f139190615db5565b61361e565b3381610f2482826135a1565b610f405760405162461bcd60e51b8152600401610cb590615be3565b610f4b8585856136af565b5050505050565b60865460ff1615610f755760405162461bcd60e51b8152600401610cb590615b50565b6000828152601a6020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015290610fbc6137e6565b5090506000610fcc85848461386b565b91505080610f4b57600654600854610ff3916001600160a01b0391821691339116876138b2565b6000858152601a602052604081206002018054869290611014908490615c52565b925050819055507f10c4de39a7e804616cdc1b2dbf59fe6db0ed0d54ff69cef9c8fc024f79c7d47e8585856040015161104d9190615c52565b604080519283526020830191909152015b60405180910390a15050505050565b60008281526022602052604090206001015461108981336138f0565b610d8d8383613970565b6001600160a01b03811633146110d05760405162461bcd60e51b8152602060048201526002602482015261373160f01b6044820152606401610cb5565b6110da82826139f5565b5050565b600080516020615faa8339815191526110f781336138f0565b600e805467ffffffffffffffff60801b1916600160801b6001600160401b038516908102919091179091556040519081527f0cedd128b637e635da421319ae981d7968b7a477c1fa3b10275fac22ecbd51a6906020015b60405180910390a15050565b600080516020615faa83398151915261117381336138f0565b828280518251148015611187575060008251115b6111b75760405162461bcd60e51b81526020600482015260016024820152603560f81b6044820152606401610cb5565b60005b600182516111c89190615e03565b811161130557633b9aca006001600160401b03168282815181106111ee576111ee615f15565b60200260200101516001600160401b03161115801561123c5750633b9aca006001600160401b031683828151811061122857611228615f15565b60200260200101516001600160401b031611155b61126c5760405162461bcd60e51b81526020600482015260016024820152601b60f91b6044820152606401610cb5565b80156112f3578261127e600183615e03565b8151811061128e5761128e615f15565b60200260200101516001600160401b03168382815181106112b1576112b1615f15565b60200260200101516001600160401b0316116112f35760405162461bcd60e51b81526020600482015260016024820152603760f81b6044820152606401610cb5565b806112fd81615eba565b9150506111ba565b508451611319906011906020880190614f17565b50835161132d906012906020870190614f17565b507f275781d4ec4992e53f64326606b9f7eb81a89baf476df8de6d0410fd218e7be36011601260405161105e929190615b18565b60118181548110610e7557600080fd5b6018546001600160a01b0316331461139b5760405162461bcd60e51b8152600401610cb590615bc8565b6113a3613a78565b60175560135442106113c4576015546113bc9082615c95565b601455611406565b6000426013546113d49190615e03565b90506000601454826113e69190615db5565b6015549091506113f68285615c52565b6114009190615c95565b60145550505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561144a57600080fd5b505afa15801561145e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611482919061563c565b9050601554816114929190615c95565b60145411156114c85760405162461bcd60e51b8152602060048201526002602482015261191960f11b6044820152606401610cb5565b4260168190556015546114da91615c52565b6013556040518281527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9060200161114e565b600080516020615faa83398151915261152681336138f0565b61152e613ae0565b50565b610d8d838383604051806020016040528060008152506127d5565b600061155883836135a1565b9392505050565b600080516020615f8a83398151915261157881336138f0565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020615faa8339815191526115b481336138f0565b600f839055601082905560408051848152602081018490527fa0aa01eac9422dea36b84eb0bbc758e72643fbdbc72a4fd205d51c738803598291015b60405180910390a1505050565b602154610100900460ff1680611616575060215460ff16155b6116325760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015611654576021805461ffff19166101011790555b816001600160a01b03811661168f5760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b611697613b73565b61169f613bee565b600680546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a91600480820192602092909190829003018186803b1580156116f357600080fd5b505afa158015611707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172b9190615167565b600860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550836001600160a01b0316636ac5dc466040518163ffffffff1660e01b815260040160206040518083038186803b15801561178a57600080fd5b505afa15801561179e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c29190615167565b600780546001600160a01b03199081166001600160a01b0393841617909155600580549091168583161790556008546040805163313ce56760e01b81529051919092169163313ce567916004808301926020929190829003018186803b15801561182b57600080fd5b505afa15801561183f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611863919061573e565b61186e90600a615d0a565b60005560065461189690600080516020615f8a833981519152906001600160a01b0316613c4d565b6118bc600080516020615faa833981519152600080516020615f8a833981519152613c57565b6118d4600080516020615f8a83398151915280613c57565b6118dc613cab565b508015610d8d576021805461ff0019169055505050565b600b8181548110610e7557600080fd5b6000818152601a602052604081208054600390910154610c6b9184916119299190615db5565b613d03565b600080516020615faa83398151915261194781336138f0565b82633b9aca00816001600160401b031611156119895760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b82633b9aca00816001600160401b031611156119cb5760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b836001600160401b0316856001600160401b03161115611a115760405162461bcd60e51b81526020600482015260016024820152600760fb1b6044820152606401610cb5565b600d80546fffffffffffffffffffffffffffffffff16600160c01b6001600160401b038781169190910267ffffffffffffffff60801b191691909117600160801b91881691820217909155600754604051635b749f3560e01b815260048101929092526001600160a01b031690635b749f3590602401600060405180830381600087803b158015611aa157600080fd5b505af1158015611ab5573d6000803e3d6000fd5b5050604080516001600160401b03808a168252881660208201527f686faddec2d8b23f0f43c10006482b63941b927c9a98339cd78514b67139ad67935001905061105e565b600080516020615faa833981519152611b1381336138f0565b8151611b26906019906020850190614fcf565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad8260405161114e9190615b3d565b6000610c6b82613482565b60198054611b6e90615e85565b80601f0160208091040260200160405190810160405280929190818152602001828054611b9a90615e85565b8015611be75780601f10611bbc57610100808354040283529160200191611be7565b820191906000526020600020905b815481529060010190602001808311611bca57829003601f168201915b505050505081565b60865460ff1615611c125760405162461bcd60e51b8152600401610cb590615b50565b3383611c1e82826135a1565b611c3a5760405162461bcd60e51b8152600401610cb590615be3565b6000858152601a6020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015290611c816137e6565b509050600080611c9289858561386b565b915091508060001415611e1f57600e5460208501514291611cc491600160801b9091046001600160401b031690615c52565b11158015611cd157508188105b8015611ce05750836040015188105b8015611d255750600d54600160401b90046001600160401b0316611d048984615e03565b611d0e9190615db5565b633b9aca008560600151611d229190615db5565b11155b8015611d725750600d546040850151600160401b9091046001600160401b031690611d51908a90615e03565b611d5b9190615db5565b633b9aca008560600151611d6f9190615db5565b11155b611da35760405162461bcd60e51b8152602060048201526002602482015261333360f01b6044820152606401610cb5565b6000898152601a6020526040812060020180548a9290611dc4908490615e03565b925050819055507f10c4de39a7e804616cdc1b2dbf59fe6db0ed0d54ff69cef9c8fc024f79c7d47e89898660400151611dfd9190615e03565b6040805192835260208301919091520160405180910390a1611e1f8789613d67565b505050505050505050565b60006001600160a01b038216611e665760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b506001600160a01b03166000908152601e602052604090205490565b6007546001600160a01b03163314611eac5760405162461bcd60e51b8152600401610cb590615bc8565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60865460ff1615611ef15760405162461bcd60e51b8152600401610cb590615b50565b6000611efb6137e6565b5090506000805b8351811015611fd4576000848281518110611f1f57611f1f615f15565b60200260200101519050611f4a816000908152601d60205260409020546001600160a01b0316151590565b15611fc1576000818152601a602090815260408083208151608081018352815481526001820154938101939093526002810154918301919091526003015460608201529080611f9a84848961386b565b915091508060011415611fbd57611fb082613eb7565b611fba9087615c52565b95505b5050505b5080611fcc81615eba565b915050611f02565b5060408051338152602081018390527f4a9b62c74532d4448574775253ac495abc6f658b1284e9f28508a23135eeb641910160405180910390a1610d8d3382613d67565b600080516020615faa83398151915261203181336138f0565b838380518251148015612045575060008251115b6120755760405162461bcd60e51b81526020600482015260016024820152603560f81b6044820152606401610cb5565b60005b600182516120869190615e03565b81116121c357633b9aca006001600160401b03168282815181106120ac576120ac615f15565b60200260200101516001600160401b0316111580156120fa5750633b9aca006001600160401b03168382815181106120e6576120e6615f15565b60200260200101516001600160401b031611155b61212a5760405162461bcd60e51b81526020600482015260016024820152601b60f91b6044820152606401610cb5565b80156121b1578261213c600183615e03565b8151811061214c5761214c615f15565b60200260200101516001600160401b031683828151811061216f5761216f615f15565b60200260200101516001600160401b0316116121b15760405162461bcd60e51b81526020600482015260016024820152603760f81b6044820152606401610cb5565b806121bb81615eba565b915050612078565b508360ff16600114156121fd5785516121e3906009906020890190614f17565b5084516121f790600a906020880190614f17565b50612226565b855161221090600b906020890190614f17565b50845161222490600c906020880190614f17565b505b7f03c94e5b4f32a4b9a2709b098207aebe4cc92c950987ee077776cc2300adcde286868660405161225993929190615adf565b60405180910390a1505050505050565b600080516020615faa83398151915261228281336138f0565b61152e613cab565b6018546001600160a01b031633146122b45760405162461bcd60e51b8152600401610cb590615bc8565b601880546001600160a01b0319166001600160a01b0383169081179091556040517f1c794a043683a294127c95bc365bae91b63b651eb9884a2c9120afee2bb690b490600090a250565b6001600160a01b03821633141561233c5760405162461bcd60e51b8152602060048201526002602482015261199b60f11b6044820152606401610cb5565b336000818152602080805260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516123a7911515815260200190565b60405180910390a35050565b60006123c160865460ff1690565b156123de5760405162461bcd60e51b8152600401610cb590615b50565b856001600160a01b0381166124195760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b6000851161244e5760405162461bcd60e51b8152602060048201526002602482015261323760f01b6044820152606401610cb5565b60065460085461246d916001600160a01b0391821691339116896138b2565b60006124776137e6565b915050848111156124af5760405162461bcd60e51b8152602060048201526002602482015261064760f31b6044820152606401610cb5565b600080546124bd8389615db5565b6124c79190615c95565b905060006124d689838a613efa565b90508581101561250d5760405162461bcd60e51b8152602060048201526002602482015261323960f01b6044820152606401610cb5565b600d5461252b908290600160401b90046001600160401b0316615db5565b612539633b9aca008a615db5565b111561256c5760405162461bcd60e51b8152602060048201526002602482015261033360f41b6044820152606401610cb5565b61257a600280546001019055565b600254945061258a8560006140b0565b816001600082825461259c9190615c52565b909155505060408051608081018252848152426020808301918252828401858152606084018d815260008b8152601a90935294909120925183559051600183015551600282015590516003909101556125f58a866140f6565b6040805186815260208101859052908101829052606081018990527f2af29ed8e180e9bfa65515c22e3af766d15e852ec59b9666d6eeaef8a97565929060800160405180910390a15050505095945050505050565b600080516020615f8a83398151915261266381336138f0565b60005b85518110156126b2576126a0600080516020615faa83398151915287838151811061269357612693615f15565b6020026020010151613970565b806126aa81615eba565b915050612666565b506126cb600080516020615faa83398151915285613970565b6007546126f090600080516020615faa833981519152906001600160a01b0316613970565b50600480546001600160a01b039384166001600160a01b031991821617909155600380549290931691161790555050565b600080516020615faa83398151915261273a81336138f0565b81633b9aca00816001600160401b0316111561277c5760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b600e80546001600160c01b0316600160c01b6001600160401b038681168202929092179283905560405192041681527f264a4c2e5ed86659859b3c52d1b00a899950c0f3a637d68ca438cc0216dd89bf906020016115f0565b33826127e182826135a1565b6127fd5760405162461bcd60e51b8152600401610cb590615be3565b612809868686866141c6565b505050505050565b60865460ff16156128345760405162461bcd60e51b8152600401610cb590615b50565b60008061283f6137e6565b915091506000600760009054906101000a90046001600160a01b03166001600160a01b031663344844db6040518163ffffffff1660e01b815260040160206040518083038186803b15801561289357600080fd5b505afa1580156128a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cb919061563c565b600d54909150600090633b9aca00906128f490600160801b90046001600160401b031684615db5565b6128fe9190615c95565b600d54909150633b9aca009061292490600160c01b90046001600160401b031684615db5565b61292e9190615c95565b600154116129635760405162461bcd60e51b81526020600482015260026024820152610ccd60f21b6044820152606401610cb5565b600080600087516001600160401b0381111561298157612981615f2b565b6040519080825280602002602001820160405280156129c657816020015b604080518082019091526000808252602082015281526020019060019003908161299f5790505b50905060005b8851811015612b825760008982815181106129e9576129e9615f15565b6020908102919091018101516000818152601d9092526040909120549091506001600160a01b03168015612b6d576000828152601a602090815260408083208151608081018352815481526001820154938101939093526002810154918301919091526003015460608201529080612a6285848f61386b565b915091508060011415612a8957612a7882613eb7565b612a82908a615c52565b9850612b56565b600e5460208401514291612aae91600160801b9091046001600160401b031690615c52565b11612b5657612abd858461420e565b60006001548b1115612aed578a633b9aca00600154612adc9190615db5565b612ae69190615c95565b9050612af4565b50633b9aca005b600080612b0685876060015185614269565b9092509050612b15818c615c52565b9a506040518060400160405280886001600160a01b03168152602001838152508a8a81518110612b4757612b47615f15565b60200260200101819052505050505b8960015411612b69575050505050612b82565b5050505b50508080612b7a90615eba565b9150506129cc565b5060008415612bb757612b96856002615db5565b633b9aca00600154612ba89190615db5565b612bb29190615c95565b612bba565b60005b9050633b9aca00612cd0826011805480602002602001604051908101604052809291908181526020018280548015612c4357602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411612c005790505b50505050506012805480602002602001604051908101604052809291908181526020018280548015612cc657602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411612c835790505b50505050506143dd565b612ce3906001600160401b031685615db5565b612ced9190615c95565b92506010548310612d0057601054612d02565b825b92506000633b9aca00612d1789612710615db5565b612d219190615db5565b600054600d548990612d4c906001600160401b03600160801b8204811691600160c01b900416615e1a565b612d57906005615dd4565b6001600160401b0316612d6a9190615db5565b612d749190615db5565b612d7e9190615c95565b9050808410612d8d5780612d8f565b835b93507fb789efbabfeba5ae006c34c3b3c17f6b1cf34ab2ac684be93d1e64da000b5be78a8433612dbf8989615c52565b604051612dcf9493929190615a33565b60405180910390a160005b8a51811015612e5f576000848281518110612df757612df7615f15565b6020026020010151602001511115612e4d57612e4d848281518110612e1e57612e1e615f15565b602002602001015160000151858381518110612e3c57612e3c615f15565b602002602001015160200151613d67565b80612e5781615eba565b915050612dda565b50612e7333612e6e8787615c52565b613d67565b50505050505050505050565b60098181548110610e7557600080fd5b6004546001600160a01b03163314612eb95760405162461bcd60e51b8152600401610cb590615bc8565b600e80546001600160401b03928316600160401b026001600160801b03199091169290931691909117919091179055565b6000818152601d60205260409020546060906001600160a01b0316612f355760405162461bcd60e51b81526020600482015260016024820152601960f91b6044820152606401610cb5565b8160005b8115612f5f5780612f4981615eba565b9150612f589050600a83615c95565b9150612f39565b6000816001600160401b03811115612f7957612f79615f2b565b6040519080825280601f01601f191660200182016040528015612fa3576020820181803683370190505b5090505b841561300e57612fb8600183615e03565b9150612fc5600a86615ed5565b612fd0906030615c52565b60f81b818381518110612fe557612fe5615f15565b60200101906001600160f81b031916908160001a905350613007600a86615c95565b9450612fa7565b60006019805461301d90615e85565b905011613039576040518060200160405280600081525061305d565b60198160405160200161304d9291906158ee565b6040516020818303038152906040525b95945050505050565b60128181548110610e7557600080fd5b60008281526022602052604090206001015461309281336138f0565b610d8d83836139f5565b600c8181548110610e7557600080fd5b6000828152601a6020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015281906130f68185614726565b92509250509250929050565b600080516020615faa83398151915261311b81336138f0565b816001600160a01b0381166131565760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610cb5565b6015849055601880546001600160a01b0319166001600160a01b0385169081179091556040518581527fe139be2fc520b685c93d718b643b5d8c42fc57b5724201180c5d765635467312906020015b60405180910390a250505050565b60865460ff16156131d65760405162461bcd60e51b8152600401610cb590615b50565b33836131e282826135a1565b6131fe5760405162461bcd60e51b8152600401610cb590615be3565b6000858152601a60209081526040808320815160808101835281548152600182015493810193909352600281015491830191909152600301546060820152906132456137e6565b50905060008061325689858561386b565b915091508060001415611e1f57600e546020850151429161328891600160801b9091046001600160401b031690615c52565b11156132bb5760405162461bcd60e51b8152602060048201526002602482015261333160f01b6044820152606401610cb5565b6132c5898561420e565b60006132e08386606001516132db6001546147ce565b614269565b509050878110156133185760405162461bcd60e51b8152602060048201526002602482015261199960f11b6044820152606401610cb5565b604080518b8152602081018390527f2f06d076c30d294b959d7aa34f40d448e45f487492a47889f02831bb06fee6bf910160405180910390a1612e738982613d67565b600080516020615faa83398151915261337481336138f0565b81633b9aca00816001600160401b031611156133b65760405162461bcd60e51b81526020600482015260016024820152600d60fa1b6044820152606401610cb5565b6133c08385615dd4565b6001600160401b03166133d86002633b9aca00615d0a565b116134095760405162461bcd60e51b81526020600482015260016024820152600760fb1b6044820152606401610cb5565b600d80546001600160801b031916600160401b6001600160401b0387811691820267ffffffffffffffff1916929092179186169182179092556040805192835260208301919091527fb556fe5cb4a1a8243b8d5000bbefd6f8b868adcac2765cd4a30ac9320ff1a0b6910160405180910390a150505050565b6000818152601d60205260409020546001600160a01b0316806134cb5760405162461bcd60e51b81526020600482015260016024820152601960f91b6044820152606401610cb5565b919050565b6000818152601f6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061350582613482565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6040516001600160a01b038316602482015260448101829052610d8d90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148c7565b6000806135ad83613482565b9050806001600160a01b0316846001600160a01b031614806135e857506000838152601f60205260409020546001600160a01b038581169116145b8061361657506001600160a01b038082166000908152602080805260408083209388168352929052205460ff165b949350505050565b61362882826140b0565b6000828152601c60205260409020548015610d8d576000838152601c60209081526040808320839055601d9091529020546005546001600160a01b03918216916136749116828461353e565b806001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486836040516131a591815260200190565b826001600160a01b03166136c282613482565b6001600160a01b0316146136e85760405162461bcd60e51b8152600401610cb590615bc8565b6001600160a01b0382166137235760405162461bcd60e51b8152602060048201526002602482015261191b60f11b6044820152606401610cb5565b61372e6000826134d0565b6001600160a01b0383166000908152601e60205260408120805460019290613757908490615e03565b90915550506001600160a01b0382166000908152601e60205260408120805460019290613785908490615c52565b90915550506000818152601d602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600354604080516341f654f760e01b8152815160009384936001600160a01b03909116926341f654f79260048083019392829003018186803b15801561382b57600080fd5b505afa15801561383f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613863919061569e565b915091509091565b600080600080600061387d8787614726565b9150915081600014806138905750806001145b156138a45761389f888861420e565b600192505b50925090505b935093915050565b6040516001600160a01b03808516602483015283166044820152606481018290526138ea9085906323b872dd60e01b9060840161356a565b50505050565b60008281526022602090815260408083206001600160a01b038516845290915290205460ff166110da5761392e816001600160a01b03166014614999565b613939836020614999565b60405160200161394a92919061598c565b60408051601f198184030181529082905262461bcd60e51b8252610cb591600401615b3d565b60008281526022602090815260408083206001600160a01b038516845290915290205460ff166110da5760008281526022602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60008281526022602090815260408083206001600160a01b038516845290915290205460ff16156110da5760008281526022602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600060015460001415613a8c575060175490565b600154670de0b6b3a7640000601454601654613aa6614b34565b613ab09190615e03565b613aba9190615db5565b613ac49190615db5565b613ace9190615c95565b601754613adb9190615c52565b905090565b60865460ff16613b295760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610cb5565b6086805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b602154610100900460ff1680613b8c575060215460ff16155b613ba85760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015613bca576021805461ffff19166101011790555b613bd2614b4f565b613bda614bb9565b801561152e576021805461ff001916905550565b602154610100900460ff1680613c07575060215460ff16155b613c235760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015613c45576021805461ffff19166101011790555b613bda614b4f565b6110da8282613970565b600082815260226020526040902060010154819060405184907fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff90600090a460009182526022602052604090912060010155565b60865460ff1615613cce5760405162461bcd60e51b8152600401610cb590615b50565b6086805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613b563390565b6000828152601c60209081526040808320548354601b90935290832054909190670de0b6b3a764000090613d35613a78565b613d3f9190615e03565b613d499086615db5565b613d539190615c95565b613d5d9190615c95565b6115589190615c52565b60065460408051629032ff60e51b815290516000926001600160a01b0316916312065fe0916004808301926020929190829003018186803b158015613dab57600080fd5b505afa158015613dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613de3919061563c565b9050818110158015613df55750600082115b15613e1857600654600854610d8d916001600160a01b03918216911685856138b2565b8115610d8d576000613e2a8284615e03565b600654600854919250613e4b916001600160a01b03908116911686856138b2565b600754604051631a115ff160e01b8152600481018390526001600160a01b03868116602483015290911690631a115ff190604401600060405180830381600087803b158015613e9957600080fd5b505af1158015613ead573d6000803e3d6000fd5b5050505050505050565b600e54600090633b9aca0090613edd90600160c01b90046001600160401b031684615db5565b613ee79190615c95565b9050600f5481106134cb57600f54610c6b565b600080613f1384600154613f0e9190615c52565b6147ce565b9050633b9aca006001600160401b03821610613f565760405162461bcd60e51b8152602060048201526002602482015261323560f01b6044820152606401610cb5565b6000633b9aca00614042836009805480602002602001604051908101604052809291908181526020018280548015613fdf57602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b031681526020019060080190602082600701049283019260010382029150808411613f9c5790505b5050505050600a805480602002602001604051908101604052809291908181526020018280548015612cc657600091825260209182902080546001600160401b03168452908202830192909160089101808411612c8357905050505050506143dd565b600e5461405891906001600160401b0316615dd4565b6001600160401b031661406b9190615c95565b9050633b9aca0061407c8282615e03565b6140869086615db5565b6140909190615c95565b61409a9085615e03565b90506140a68187615e03565b9695505050505050565b6140b8613a78565b6017556140c3614b34565b6016556140d08282613d03565b6000928352601c6020908152604080852092909255601754601b90915292209190915550565b6001600160a01b0382166000908152601e6020526040812080546001929061411f908490615c52565b90915550506000818152601d602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46141956000838360405180602001604052806000815250614c2e565b6110da5760405162461bcd60e51b81526020600482015260026024820152610c8d60f21b6044820152606401610cb5565b6141d18484846136af565b6141dd84848484614c2e565b6138ea5760405162461bcd60e51b81526020600482015260026024820152610c8d60f21b6044820152606401610cb5565b8051606082015160009161422191615db5565b905061422d838261361e565b6000838152601b60205260408120819055546142499082615c95565b6001600082825461425a9190615e03565b90915550610d8d905083614d50565b600080633b9aca0061435684600b8054806020026020016040519081016040528092919081815260200182805480156142f357602002820191906000526020600020906000905b82829054906101000a90046001600160401b03166001600160401b0316815260200190600801906020826007010492830192600103820291508084116142b05790505b5050505050600c805480602002602001604051908101604052809291908181526020018280548015612cc657600091825260209182902080546001600160401b03168452908202830192909160089101808411612c8357905050505050506143dd565b600e546143739190600160401b90046001600160401b0316615dd4565b6001600160401b03166143869190615c95565b9050633b9aca006143978282615e03565b6143a19086615db5565b6143ab9190615c95565b6143b59085615e03565b90508481106143c9575060009050836138aa565b6143d38186615e03565b9150935093915050565b600082600184516143ee9190615e03565b815181106143fe576143fe615f15565b60200260200101516001600160401b0316846001600160401b03161061444c57816001845161442d9190615e03565b8151811061443d5761443d615f15565b60200260200101519050611558565b8260008151811061445f5761445f615f15565b60200260200101516001600160401b0316846001600160401b031611614492578160008151811061443d5761443d615f15565b600080600185516144a39190615e03565b905060005b60016144b48484615e03565b111561451e5760026144c68484615e03565b6144d09190615c95565b6144da9084615c52565b9050866001600160401b03168682815181106144f8576144f8615f15565b60200260200101516001600160401b031611614516578092506144a8565b8091506144a8565b84838151811061453057614530615f15565b60200260200101516001600160401b031685838151811061455357614553615f15565b60200260200101516001600160401b0316111561464d5785838151811061457c5761457c615f15565b602002602001015186838151811061459657614596615f15565b60200260200101516145a89190615e1a565b8684815181106145ba576145ba615f15565b6020026020010151886145cd9190615e1a565b8685815181106145df576145df615f15565b60200260200101518785815181106145f9576145f9615f15565b602002602001015161460b9190615e1a565b6146159190615dd4565b61461f9190615ca9565b85848151811061463157614631615f15565b60200260200101516146439190615c6a565b9350505050611558565b85838151811061465f5761465f615f15565b602002602001015186838151811061467957614679615f15565b602002602001015161468b9190615e1a565b86848151811061469d5761469d615f15565b6020026020010151886146b09190615e1a565b8684815181106146c2576146c2615f15565b60200260200101518786815181106146dc576146dc615f15565b60200260200101516146ee9190615e1a565b6146f89190615dd4565b6147029190615ca9565b85848151811061471457614714615f15565b60200260200101516146439190615e1a565b600080600083856000015186606001516147409190615db5565b61474a9190615c95565b9050846040015185606001516147609190615c52565b811061476f57600092506147c6565b80856040015186606001516147849190615c52565b61478e9190615e03565b600d5460608701519194506147ae916001600160401b0390911690615db5565b6147bc633b9aca0085615db5565b116147c657600191505b509250929050565b600080633b9aca00600d60109054906101000a90046001600160401b03166001600160401b0316600760009054906101000a90046001600160a01b03166001600160a01b031663344844db6040518163ffffffff1660e01b815260040160206040518083038186803b15801561484357600080fd5b505afa158015614857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061487b919061563c565b6148859190615db5565b61488f9190615c95565b9050808310156148b957806148a8633b9aca0085615db5565b6148b29190615c95565b91506148c1565b633b9aca0091505b50919050565b600061491c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614e0c9092919063ffffffff16565b805190915015610d8d578080602001905181019061493a919061555f565b610d8d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cb5565b606060006149a8836002615db5565b6149b3906002615c52565b6001600160401b038111156149ca576149ca615f2b565b6040519080825280601f01601f1916602001820160405280156149f4576020820181803683370190505b509050600360fc1b81600081518110614a0f57614a0f615f15565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614a3e57614a3e615f15565b60200101906001600160f81b031916908160001a9053506000614a62846002615db5565b614a6d906001615c52565b90505b6001811115614ae5576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614aa157614aa1615f15565b1a60f81b828281518110614ab757614ab7615f15565b60200101906001600160f81b031916908160001a90535060049490941c93614ade81615e6e565b9050614a70565b5083156115585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610cb5565b6000806013544210614b4857601354610c6b565b4292915050565b602154610100900460ff1680614b68575060215460ff16155b614b845760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015613bda576021805461ffff1916610101179055801561152e576021805461ff001916905550565b602154610100900460ff1680614bd2575060215460ff16155b614bee5760405162461bcd60e51b8152600401610cb590615b7a565b602154610100900460ff16158015614c10576021805461ffff19166101011790555b6086805460ff19169055801561152e576021805461ff001916905550565b60006001600160a01b0384163b15614d4557604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614c72903390899088908890600401615a01565b602060405180830381600087803b158015614c8c57600080fd5b505af1925050508015614cbc575060408051601f3d908101601f19168201909252614cb9918101906155d7565b60015b614d2b573d808015614cea576040519150601f19603f3d011682016040523d82523d6000602084013e614cef565b606091505b508051614d235760405162461bcd60e51b81526020600482015260026024820152610c8d60f21b6044820152606401610cb5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613616565b506001949350505050565b6000614d5b82613482565b9050614d686000836134d0565b6001600160a01b0381166000908152601e60205260408120805460019290614d91908490615e03565b90915550506000828152601d6020908152604080832080546001600160a01b0319169055601a9091528082208281556001810183905560028101839055600301829055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6060613616848460008585843b614e655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cb5565b600080866001600160a01b03168587604051614e8191906158d2565b60006040518083038185875af1925050503d8060008114614ebe576040519150601f19603f3d011682016040523d82523d6000602084013e614ec3565b606091505b5091509150614ed3828286614ede565b979650505050505050565b60608315614eed575081611558565b825115614efd5782518084602001fd5b8160405162461bcd60e51b8152600401610cb59190615b3d565b82805482825590600052602060002090600301600490048101928215614fbf5791602002820160005b83821115614f8a57835183826101000a8154816001600160401b0302191690836001600160401b031602179055509260200192600801602081600701049283019260010302614f40565b8015614fbd5782816101000a8154906001600160401b030219169055600801602081600701049283019260010302614f8a565b505b50614fcb929150615043565b5090565b828054614fdb90615e85565b90600052602060002090601f016020900481019282614ffd5760008555614fbf565b82601f1061501657805160ff1916838001178555614fbf565b82800160010185558215614fbf579182015b82811115614fbf578251825591602001919060010190615028565b5b80821115614fcb5760008155600101615044565b60006001600160401b0383111561507157615071615f2b565b615084601f8401601f1916602001615bff565b905082815283838301111561509857600080fd5b828260208301376000602084830101529392505050565b80356134cb81615f41565b600082601f8301126150cb57600080fd5b813560206150e06150db83615c2f565b615bff565b80838252828201915082860187848660051b890101111561510057600080fd5b60005b858110156151265761511482615133565b84529284019290840190600101615103565b5090979650505050505050565b80356001600160401b03811681146134cb57600080fd5b60006020828403121561515c57600080fd5b813561155881615f41565b60006020828403121561517957600080fd5b815161155881615f41565b6000806040838503121561519757600080fd5b82356151a281615f41565b915060208301356151b281615f41565b809150509250929050565b6000806000606084860312156151d257600080fd5b83356151dd81615f41565b925060208401356151ed81615f41565b929592945050506040919091013590565b6000806000806080858703121561521457600080fd5b843561521f81615f41565b9350602085013561522f81615f41565b92506040850135915060608501356001600160401b0381111561525157600080fd5b8501601f8101871361526257600080fd5b61527187823560208401615058565b91505092959194509250565b6000806040838503121561529057600080fd5b823561529b81615f41565b915060208301356151b281615f56565b600080604083850312156152be57600080fd5b82356152c981615f41565b946020939093013593505050565b600080600080600060a086880312156152ef57600080fd5b85356152fa81615f41565b97602087013597506040870135966060810135965060800135945092505050565b6000806000806080858703121561533157600080fd5b84356001600160401b0381111561534757600080fd5b8501601f8101871361535857600080fd5b803560206153686150db83615c2f565b8083825282820191508285018b848660051b880101111561538857600080fd5b600095505b848610156153b45780356153a081615f41565b83526001959095019491830191830161538d565b5097506153c490508882016150af565b95505050506153d5604086016150af565b91506153e3606086016150af565b905092959194509250565b6000602080838503121561540157600080fd5b82356001600160401b0381111561541757600080fd5b8301601f8101851361542857600080fd5b80356154366150db82615c2f565b80828252848201915084840188868560051b870101111561545657600080fd5b600094505b8385101561547957803583526001949094019391850191850161545b565b50979650505050505050565b6000806040838503121561549857600080fd5b82356001600160401b03808211156154af57600080fd5b6154bb868387016150ba565b935060208501359150808211156154d157600080fd5b506154de858286016150ba565b9150509250929050565b6000806000606084860312156154fd57600080fd5b83356001600160401b038082111561551457600080fd5b615520878388016150ba565b9450602086013591508082111561553657600080fd5b50615543868287016150ba565b925050604084013561555481615f7a565b809150509250925092565b60006020828403121561557157600080fd5b815161155881615f56565b60006020828403121561558e57600080fd5b5035919050565b600080604083850312156155a857600080fd5b8235915060208301356151b281615f41565b6000602082840312156155cc57600080fd5b813561155881615f64565b6000602082840312156155e957600080fd5b815161155881615f64565b60006020828403121561560657600080fd5b81356001600160401b0381111561561c57600080fd5b8201601f8101841361562d57600080fd5b61361684823560208401615058565b60006020828403121561564e57600080fd5b5051919050565b60008060006060848603121561566a57600080fd5b8335925060208401356151ed81615f41565b6000806040838503121561568f57600080fd5b50508035926020909101359150565b600080604083850312156156b157600080fd5b505080516020909101519092909150565b6000806000606084860312156156d757600080fd5b8335925060208401359150604084013561555481615f41565b60006020828403121561570257600080fd5b61155882615133565b6000806040838503121561571e57600080fd5b61572783615133565b915061573560208401615133565b90509250929050565b60006020828403121561575057600080fd5b815161155881615f7a565b600081518084526020808501945080840160005b838110156157945781516001600160401b03168752958201959082019060010161576f565b509495945050505050565b805480835260008281526020808220940193909190825b826003820110156158055781546001600160401b038082168852604082811c821660208a0152608083811c9092169089015260c09190911c6060880152909501946001909101906004016157b6565b90549082811015615826576001600160401b03821686526020909501946001015b82811015615848576001600160401b03604083901c1686526020909501946001015b8281101561586a576001600160401b03608083901c1686526020909501946001015b828110156158805760c082901c86526020860195505b5093949350505050565b600081518084526158a2816020860160208601615e42565b601f01601f19169290920160200192915050565b600081516158c8818560208601615e42565b9290920192915050565b600082516158e4818460208701615e42565b9190910192915050565b600080845481600182811c91508083168061590a57607f831692505b602080841082141561592a57634e487b7160e01b86526022600452602486fd5b81801561593e576001811461594f5761597c565b60ff1986168952848901965061597c565b60008b81526020902060005b868110156159745781548b82015290850190830161595b565b505084890196505b50505050505061305d81856158b6565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516159c4816017850160208801615e42565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516159f5816028840160208801615e42565b01602801949350505050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526140a6608083018461588a565b6080808252855190820181905260009060209060a0840190828901845b82811015615a6c57815184529284019290840190600101615a50565b5050508381038285015286518082528783019183019060005b81811015615ab557835180516001600160a01b031684528501518584015292840192604090920191600101615a85565b50506001600160a01b03871660408601529250615ad0915050565b82606083015295945050505050565b606081526000615af2606083018661575b565b8281036020840152615b04818661575b565b91505060ff83166040830152949350505050565b604081526000615b2b604083018561579f565b828103602084015261305d818561579f565b602081526000611558602083018461588a565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252600190820152603160f81b604082015260600190565b602080825260029082015261323160f01b604082015260600190565b604051601f8201601f191681016001600160401b0381118282101715615c2757615c27615f2b565b604052919050565b60006001600160401b03821115615c4857615c48615f2b565b5060051b60200190565b60008219821115615c6557615c65615ee9565b500190565b60006001600160401b03808316818516808303821115615c8c57615c8c615ee9565b01949350505050565b600082615ca457615ca4615eff565b500490565b60006001600160401b0380841680615cc357615cc3615eff565b92169190910492915050565b600181815b808511156147c6578160001904821115615cf057615cf0615ee9565b80851615615cfd57918102915b93841c9390800290615cd4565b600061155860ff841683600082615d2357506001610c6b565b81615d3057506000610c6b565b8160018114615d465760028114615d5057615d6c565b6001915050610c6b565b60ff841115615d6157615d61615ee9565b50506001821b610c6b565b5060208310610133831016604e8410600b8410161715615d8f575081810a610c6b565b615d998383615ccf565b8060001904821115615dad57615dad615ee9565b029392505050565b6000816000190483118215151615615dcf57615dcf615ee9565b500290565b60006001600160401b0380831681851681830481118215151615615dfa57615dfa615ee9565b02949350505050565b600082821015615e1557615e15615ee9565b500390565b60006001600160401b0383811690831681811015615e3a57615e3a615ee9565b039392505050565b60005b83811015615e5d578181015183820152602001615e45565b838111156138ea5750506000910152565b600081615e7d57615e7d615ee9565b506000190190565b600181811c90821680615e9957607f821691505b602082108114156148c157634e487b7160e01b600052602260045260246000fd5b6000600019821415615ece57615ece615ee9565b5060010190565b600082615ee457615ee4615eff565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461152e57600080fd5b801515811461152e57600080fd5b6001600160e01b03198116811461152e57600080fd5b60ff8116811461152e57600080fdfe5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56255435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041a264697066735822122045840058006f230868797238b1a0691e6a0b163718211cd780d1fcfd01a5532c64736f6c63430008070033

Deployed Bytecode Sourcemap

129868:29978:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159197:646;;;;;;:::i;:::-;;:::i;:::-;;;22924:14:1;;22917:22;22899:41;;22887:2;22872:18;159197:646:0;;;;;;;;153295:100;153369:18;;;;;;;;;;;;-1:-1:-1;;;153369:18:0;;;;153295:100;;;;;;;:::i;155924:179::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;18944:55:1;;;18926:74;;18914:2;18899:18;155924:179:0;18780:226:1;155511:283:0;;;;;;:::i;:::-;;:::i;:::-;;86226:40;;;;;-1:-1:-1;;;86226:40:0;;-1:-1:-1;;;;;86226:40:0;;;;;;-1:-1:-1;;;;;36295:31:1;;;36277:50;;36265:2;36250:18;86226:40:0;36133:200:1;112864:72:0;;-1:-1:-1;;;;;;;;;;;112864:72:0;;;;;23097:25:1;;;23085:2;23070:18;112864:72:0;22951:177:1;85890:22:0;;;;;-1:-1:-1;;;85890:22:0;;-1:-1:-1;;;;;85890:22:0;;;117194:340;;;;;;:::i;:::-;;:::i;83077:30::-;;;;;;:::i;:::-;;:::i;152884:233::-;;;;;;:::i;:::-;;:::i;157477:217::-;;;;;;:::i;:::-;;:::i;45599:123::-;;;;;;:::i;:::-;45665:7;45692:12;;;:6;:12;;;;;:22;;;;45599:123;139640:657;;;;;;:::i;:::-;;:::i;112746:66::-;;-1:-1:-1;;;;;;;;;;;112746:66:0;;45984:141;;;;;;:::i;:::-;;:::i;84628:26::-;;;;;-1:-1:-1;;;84628:26:0;;-1:-1:-1;;;;;84628:26:0;;;47020:165;;;;;;:::i;:::-;;:::i;121648:162::-;;;;;;:::i;:::-;;:::i;127339:445::-;;;;;;:::i;:::-;;:::i;87334:34::-;;;;;;:::i;:::-;;:::i;87863:30::-;;;;;;115584:1290;;;;;;:::i;:::-;;:::i;119682:90::-;;;:::i;87978:34::-;;;;;-1:-1:-1;;;;;87978:34:0;;;157937:187;;;;;;:::i;:::-;;:::i;157091:169::-;;;;;;:::i;:::-;;:::i;128268:137::-;;;;;;:::i;:::-;;:::i;126394:376::-;;;;;;:::i;:::-;;:::i;130932:1463::-;;;;;;:::i;:::-;;:::i;83226:31::-;;;;;;:::i;:::-;;:::i;152448:198::-;;;;;;:::i;:::-;;:::i;124805:578::-;;;;;;:::i;:::-;;:::i;121142:154::-;;;;;;:::i;:::-;;:::i;4368:86::-;4439:7;;;;4368:86;;154907:126;;;;;;:::i;:::-;;:::i;88170:21::-;;;:::i;140841:1853::-;;;;;;:::i;:::-;;:::i;154621:161::-;;;;;;:::i;:::-;;:::i;128819:150::-;;;;;;:::i;:::-;;:::i;87831:25::-;;;;;;143469:1159;;;;;;:::i;:::-;;:::i;86520:39::-;;;;;;81376:21;;;;;-1:-1:-1;;;;;81376:21:0;;;123777:494;;;;;;:::i;:::-;;:::i;88499:62::-;;;;;;:::i;:::-;;;;;;;;;;;;;;119548:86;;;:::i;118173:232::-;;;;;;:::i;:::-;;:::i;86952:35::-;;;;;;84396:27;;;;;-1:-1:-1;;;84396:27:0;;-1:-1:-1;;;;;84396:27:0;;;85539:34;;;;;-1:-1:-1;;;85539:34:0;;-1:-1:-1;;;;;85539:34:0;;;44462:139;;;;;;:::i;:::-;44540:4;44564:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;44564:29:0;;;;;;;;;;;;;;;44462:139;72421:43;;72459:5;72421:43;;42718:49;;42763:4;42718:49;;156350:260;;;;;;:::i;:::-;;:::i;133487:2628::-;;;;;;:::i;:::-;;:::i;83949:25::-;;;;;-1:-1:-1;;;83949:25:0;;-1:-1:-1;;;;;83949:25:0;;;114512:575;;;;;;:::i;:::-;;:::i;125633:358::-;;;;;;:::i;:::-;;:::i;158374:259::-;;;;;;:::i;:::-;;:::i;80895:31::-;;;;;;145393:6026;;;;;;:::i;:::-;;:::i;85140:33::-;;;;;-1:-1:-1;;;;;85140:33:0;;;82847:30;;;;;;:::i;:::-;;:::i;118949:234::-;;;;;;:::i;:::-;;:::i;153695:752::-;;;;;;:::i;:::-;;:::i;87900:29::-;;;;;;87491:34;;;;;;:::i;:::-;;:::i;46370:143::-;;;;;;:::i;:::-;;:::i;83692:31::-;;;;;-1:-1:-1;;;;;83692:31:0;;;83317;;;;;;:::i;:::-;;:::i;82036:::-;;;;;-1:-1:-1;;;;;82036:31:0;;;87936:35;;;;;;72217:44;;72255:6;72217:44;;151975:237;;;;;;:::i;:::-;;:::i;:::-;;;;35658:25:1;;;35714:2;35699:18;;35692:34;;;;35631:18;151975:237:0;35484:248:1;120545:378:0;;;;;;:::i;:::-;;:::i;137188:1759::-;;;;;;:::i;:::-;;:::i;156803:156::-;;;;;;:::i;:::-;-1:-1:-1;;;;;156916:25:0;;;156892:4;156916:25;;;:18;:25;;;;;;;:35;;;;;;;;;;;;;;;156803:156;87797:27;;;;;;88700:42;;;;;;:::i;:::-;;;;;;;;;;;;;;122339:496;;;;;;:::i;:::-;;:::i;81947:25::-;;;;;-1:-1:-1;;;;;81947:25:0;;;88350:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35968:25:1;;;36024:2;36009:18;;36002:34;;;;36052:18;;;36045:34;36110:2;36095:18;;36088:34;35955:3;35940:19;88350:50:0;35737:391:1;159197:646:0;159285:4;-1:-1:-1;;;;;;159322:55:0;;-1:-1:-1;;;159322:55:0;;:131;;-1:-1:-1;;;;;;;159394:59:0;;-1:-1:-1;;;159394:59:0;159322:131;:196;;;-1:-1:-1;;;;;;;159470:48:0;;-1:-1:-1;;;159470:48:0;159322:196;:270;;;-1:-1:-1;;;;;;;159535:57:0;;-1:-1:-1;;;159535:57:0;159322:270;:334;;;-1:-1:-1;;;;;;;159609:47:0;;-1:-1:-1;;;159609:47:0;159322:334;:399;;;-1:-1:-1;;;;;;;159673:48:0;;-1:-1:-1;;;159673:48:0;159322:399;:456;;;-1:-1:-1;;;;;;;159738:40:0;;-1:-1:-1;;;159738:40:0;159322:456;:513;;;-1:-1:-1;;;;;;;159795:40:0;;-1:-1:-1;;;159795:40:0;159322:513;159302:533;159197:646;-1:-1:-1;;159197:646:0:o;155924:179::-;155998:7;107756:20;;;:7;:20;;;;;;-1:-1:-1;;;;;107756:20:0;156018:34;;;;-1:-1:-1;;;156018:34:0;;31468:2:1;156018:34:0;;;31450:21:1;31507:1;31487:18;;;31480:29;-1:-1:-1;;;31525:18:1;;;31518:31;31566:18;;156018:34:0;;;;;;;;;106142:7;106169:32;;;:19;:32;;;;;;-1:-1:-1;;;;;106169:32:0;156070:25;106076:133;155511:283;155590:13;155606:21;155615:11;155606:8;:21::i;:::-;155590:37;;155652:5;-1:-1:-1;;;;;155646:11:0;:2;-1:-1:-1;;;;;155646:11:0;;;155638:26;;;;-1:-1:-1;;;155638:26:0;;27408:2:1;155638:26:0;;;27390:21:1;27447:1;27427:18;;;27420:29;-1:-1:-1;;;27465:18:1;;;27458:32;27507:18;;155638:26:0;27206:325:1;155638:26:0;155683:10;-1:-1:-1;;;;;155683:19:0;;;;:58;;-1:-1:-1;;;;;;156916:25:0;;156892:4;156916:25;;;:18;:25;;;;;;;155730:10;156916:35;;;;;;;;;;155706;155675:73;;;;-1:-1:-1;;;155675:73:0;;;;;;;:::i;:::-;155761:25;155770:2;155774:11;155761:8;:25::i;:::-;155579:215;155511:283;;:::o;117194:340::-;113726:19;;-1:-1:-1;;;;;113726:19:0;113712:10;:33;113704:47;;;;-1:-1:-1;;;113704:47:0;;;;;;;:::i;:::-;117390:11:::1;::::0;-1:-1:-1;;;;;117366:36:0;;::::1;117390:11:::0;::::1;117366:36;;117358:51;;;::::0;-1:-1:-1;;;117358:51:0;;28413:2:1;117358:51:0::1;::::0;::::1;28395:21:1::0;28452:1;28432:18;;;28425:29;-1:-1:-1;;;28470:18:1;;;28463:32;28512:18;;117358:51:0::1;28211:325:1::0;117358:51:0::1;117420:50;-1:-1:-1::0;;;;;117420:33:0;::::1;117454:2:::0;117458:11;117420:33:::1;:50::i;:::-;117510:2;-1:-1:-1::0;;;;;117486:40:0::1;117496:12;-1:-1:-1::0;;;;;117486:40:0::1;;117514:11;117486:40;;;;23097:25:1::0;;23085:2;23070:18;;22951:177;117486:40:0::1;;;;;;;;117194:340:::0;;;:::o;83077:30::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;83077:30:0;;:::o;152884:233::-;4439:7;;;;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;152967:10:::1;152979:11;113502:39;113521:6;113529:11;113502:18;:39::i;:::-;113494:54;;;;-1:-1:-1::0;;;113494:54:0::1;;;;;;;:::i;:::-;153072:26:::2;::::0;;;:13:::2;:26;::::0;;;;:36;;153027:42:::2;::::0;;::::2;::::0;153003:106:::2;::::0;153014:11;;153027:81:::2;::::0;153072:36;153027:81:::2;:::i;:::-;153003:10;:106::i;157477:217::-:0;157618:10;157630:11;113502:39;113521:6;113529:11;113502:18;:39::i;:::-;113494:54;;;;-1:-1:-1;;;113494:54:0;;;;;;;:::i;:::-;157654:32:::1;157664:4;157670:2;157674:11;157654:9;:32::i;:::-;157477:217:::0;;;;;:::o;139640:657::-;4439:7;;;;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;139808:26:::1;139837::::0;;;:13:::1;:26;::::0;;;;;;;139808:55;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;;::::0;;;;;;139897:17:::1;:15;:17::i;:::-;139874:40;;;139928:18;139950:51;139968:11;139981:9;139992:8;139950:17;:51::i;:::-;139925:76:::0;-1:-1:-1;;140016:15:0;140012:278:::1;;140123:11;::::0;140079:6:::1;::::0;:65:::1;::::0;-1:-1:-1;;;;;140079:6:0;;::::1;::::0;140103:10:::1;::::0;140123:11:::1;140137:6:::0;140079:23:::1;:65::i;:::-;140159:26;::::0;;;:13:::1;:26;::::0;;;;:33:::1;;:43:::0;;140196:6;;140159:26;:43:::1;::::0;140196:6;;140159:43:::1;:::i;:::-;;;;;;;;140222:56;140239:11;140271:6;140252:9;:16;;;:25;;;;:::i;:::-;140222:56;::::0;;35658:25:1;;;35714:2;35699:18;;35692:34;;;;35631:18;140222:56:0::1;;;;;;;;139733:564;;;139640:657:::0;;:::o;45984:141::-;45665:7;45692:12;;;:6;:12;;;;;:22;;;44322:28;44333:4;44339:10;44322;:28::i;:::-;46092:25:::1;46103:4;46109:7;46092:10;:25::i;47020:165::-:0;-1:-1:-1;;;;;47110:21:0;;47121:10;47110:21;47102:36;;;;-1:-1:-1;;;47102:36:0;;25682:2:1;47102:36:0;;;25664:21:1;25721:1;25701:18;;;25694:29;-1:-1:-1;;;25739:18:1;;;25732:32;25781:18;;47102:36:0;25480:325:1;47102:36:0;47151:26;47163:4;47169:7;47151:11;:26::i;:::-;47020:165;;:::o;121648:162::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;121740:8:::1;:20:::0;;-1:-1:-1;;;;121740:20:0::1;-1:-1:-1::0;;;;;;;;121740:20:0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;121776:26:::1;::::0;36277:50:1;;;121776:26:0::1;::::0;36265:2:1;36250:18;121776:26:0::1;;;;;;;;121648:162:::0;;:::o;127339:445::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;127547:19:::1;127568;75480:6;:13;75463:6;:13;:30;:51;;;;;75513:1;75497:6;:13;:17;75463:51;75455:65;;;::::0;-1:-1:-1;;;75455:65:0;;32814:2:1;75455:65:0::1;::::0;::::1;32796:21:1::0;32853:1;32833:18;;;32826:29;-1:-1:-1;;;32871:18:1;;;32864:31;32912:18;;75455:65:0::1;32612:324:1::0;75455:65:0::1;75536:9;75531:257;75572:1;75556:6;:13;:17;;;;:::i;:::-;75551:1;:22;75531:257;;72459:5;-1:-1:-1::0;;;;;75603:32:0::1;:6;75610:1;75603:9;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75603:32:0::1;;;:68;;;;;72459:5;-1:-1:-1::0;;;;;75639:32:0::1;:6;75646:1;75639:9;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75639:32:0::1;;;75603:68;75595:82;;;::::0;-1:-1:-1;;;75595:82:0;;33884:2:1;75595:82:0::1;::::0;::::1;33866:21:1::0;33923:1;33903:18;;;33896:29;-1:-1:-1;;;33941:18:1;;;33934:31;33982:18;;75595:82:0::1;33682:324:1::0;75595:82:0::1;75696:5:::0;;75692:85:::1;;75742:6:::0;75749:5:::1;75753:1;75749::::0;:5:::1;:::i;:::-;75742:13;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75730:25:0::1;:6;75737:1;75730:9;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75730:25:0::1;;75722:39;;;::::0;-1:-1:-1;;;75722:39:0;;26342:2:1;75722:39:0::1;::::0;::::1;26324:21:1::0;26381:1;26361:18;;;26354:29;-1:-1:-1;;;26399:18:1;;;26392:31;26440:18;;75722:39:0::1;26140:324:1::0;75722:39:0::1;75575:3:::0;::::1;::::0;::::1;:::i;:::-;;;;75531:257;;;-1:-1:-1::0;127605:40:0;;::::2;::::0;:18:::2;::::0;:40:::2;::::0;::::2;::::0;::::2;:::i;:::-;-1:-1:-1::0;127656:40:0;;::::2;::::0;:18:::2;::::0;:40:::2;::::0;::::2;::::0;::::2;:::i;:::-;;127712:64;127737:18;127757;127712:64;;;;;;;:::i;87334:34::-:0;;;;;;;;;;;;115584:1290;113726:19;;-1:-1:-1;;;;;113726:19:0;113712:10;:33;113704:47;;;;-1:-1:-1;;;113704:47:0;;;;;;;:::i;:::-;115704:17:::1;:15;:17::i;:::-;115681:20;:40:::0;115757:12:::1;::::0;115738:15:::1;:31;115734:476;;115880:15;::::0;115871:24:::1;::::0;:6;:24:::1;:::i;:::-;115858:10;:37:::0;115734:476:::1;;;115928:17;115963:15;115948:12;;:30;;;;:::i;:::-;115928:50;;115993:16;116024:10;;116012:9;:22;;;;:::i;:::-;116183:15;::::0;115993:41;;-1:-1:-1;116162:17:0::1;115993:41:::0;116162:6;:17:::1;:::i;:::-;116161:37;;;;:::i;:::-;116148:10;:50:::0;-1:-1:-1;;115734:476:0::1;116592:11;::::0;:36:::1;::::0;-1:-1:-1;;;116592:36:0;;116622:4:::1;116592:36;::::0;::::1;18926:74:1::0;116574:15:0::1;::::0;-1:-1:-1;;;;;116592:11:0::1;::::0;:21:::1;::::0;18899:18:1;;116592:36:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116574:54;;116673:15;;116663:7;:25;;;;:::i;:::-;116649:10;;:39;;116641:54;;;::::0;-1:-1:-1;;;116641:54:0;;33143:2:1;116641:54:0::1;::::0;::::1;33125:21:1::0;33182:1;33162:18;;;33155:29;-1:-1:-1;;;33200:18:1;;;33193:32;33242:18;;116641:54:0::1;32941:325:1::0;116641:54:0::1;116725:15;116708:14;:32:::0;;;116816:15:::1;::::0;116798:33:::1;::::0;::::1;:::i;:::-;116783:12;:48:::0;116847:19:::1;::::0;23097:25:1;;;116847:19:0::1;::::0;23085:2:1;23070:18;116847:19:0::1;22951:177:1::0;119682:90:0;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;119754:10:::1;:8;:10::i;:::-;119682:90:::0;:::o;157937:187::-;158073:43;158090:4;158096:2;158100:11;158073:43;;;;;;;;;;;;:16;:43::i;157091:169::-;157188:4;157212:40;157231:7;157240:11;157212:18;:40::i;:::-;157205:47;157091:169;-1:-1:-1;;;157091:169:0:o;128268:137::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;-1:-1:-1;128372:11:0::1;:25:::0;;-1:-1:-1;;;;;;128372:25:0::1;-1:-1:-1::0;;;;;128372:25:0;;;::::1;::::0;;;::::1;::::0;;128268:137::o;126394:376::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;126571:24:::1;:52:::0;;;126634:20:::1;:44:::0;;;126694:68:::1;::::0;;35658:25:1;;;35714:2;35699:18;;35692:34;;;126694:68:0::1;::::0;35631:18:1;126694:68:0::1;;;;;;;;126394:376:::0;;;:::o;130932:1463::-;1592:13;;;;;;;;:30;;-1:-1:-1;1610:12:0;;;;1609:13;1592:30;1584:89;;;;-1:-1:-1;;;1584:89:0;;;;;;;:::i;:::-;1709:13;;;;;;;1708:14;1733:101;;;;1768:13;:20;;-1:-1:-1;;1803:19:0;;;;;1733:101;131066:12;-1:-1:-1;;;;;76413:24:0;::::1;76405:38;;;::::0;-1:-1:-1;;;76405:38:0;;24314:2:1;76405:38:0::1;::::0;::::1;24296:21:1::0;24353:1;24333:18;;;24326:29;-1:-1:-1;;;24371:18:1;;;24364:31;24412:18;;76405:38:0::1;24112:324:1::0;76405:38:0::1;131132:17:::2;:15;:17::i;:::-;131160:22;:20;:22::i;:::-;131227:11;:26:::0;;-1:-1:-1;;;;;;131227:26:0::2;-1:-1:-1::0;;;;;131227:26:0;::::2;::::0;;::::2;::::0;;;131280:20:::2;::::0;;-1:-1:-1;;;131280:20:0;;;;:18:::2;::::0;:20:::2;::::0;;::::2;::::0;::::2;::::0;;;;;;;;;131227:26;131280:20;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131264:6;;:37;;;;;-1:-1:-1::0;;;;;131264:37:0::2;;;;;-1:-1:-1::0;;;;;131264:37:0::2;;;;;;131342:12;-1:-1:-1::0;;;;;131342:25:0::2;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131312:13;:58:::0;;-1:-1:-1;;;;;;131312:58:0;;::::2;-1:-1:-1::0;;;;;131312:58:0;;::::2;;::::0;;;131381:11:::2;:26:::0;;;;::::2;::::0;;::::2;;::::0;;131460:6:::2;::::0;131437:42:::2;::::0;;-1:-1:-1;;;131437:42:0;;;;131460:6;;;::::2;::::0;131437:40:::2;::::0;:42:::2;::::0;;::::2;::::0;::::2;::::0;;;;;;;;131460:6;131437:42;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131432:48;::::0;:2:::2;:48;:::i;:::-;131418:11;:62:::0;131995:11:::2;::::0;131958:50:::2;::::0;-1:-1:-1;;;;;;;;;;;112907:29:0;-1:-1:-1;;;;;131995:11:0::2;131958:10;:50::i;:::-;132121:46;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;;;132121:13:0::2;:46::i;:::-;132178:49;-1:-1:-1::0;;;;;;;;;;;112907:29:0;132178:13:::2;:49::i;:::-;132379:8;:6;:8::i;:::-;1846:1:::1;1864:14:::0;1860:68;;;1895:13;:21;;-1:-1:-1;;1895:21:0;;;1573:362;130932:1463;;:::o;83226:31::-;;;;;;;;;;;;152448:198;152508:7;152601:26;;;:13;:26;;;;;:36;;152556:42;;;;;152535:103;;152543:11;;152556:81;;152601:36;152556:81;:::i;:::-;152535:7;:103::i;124805:578::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;124981:14:::1;72459:5;76078:4;-1:-1:-1::0;;;;;76078:19:0::1;;;76070:33;;;::::0;-1:-1:-1;;;76070:33:0;;25353:2:1;76070:33:0::1;::::0;::::1;25335:21:1::0;25392:1;25372:18;;;25365:29;-1:-1:-1;;;25410:18:1;;;25403:31;25451:18;;76070:33:0::1;25151:324:1::0;76070:33:0::1;125025:13:::2;72459:5;76078:4;-1:-1:-1::0;;;;;76078:19:0::2;;;76070:33;;;::::0;-1:-1:-1;;;76070:33:0;;25353:2:1;76070:33:0::2;::::0;::::2;25335:21:1::0;25392:1;25372:18;;;25365:29;-1:-1:-1;;;25410:18:1;;;25403:31;25451:18;;76070:33:0::2;25151:324:1::0;76070:33:0::2;125082:13:::3;-1:-1:-1::0;;;;;125064:31:0::3;:14;-1:-1:-1::0;;;;;125064:31:0::3;;;125056:45;;;::::0;-1:-1:-1;;;125056:45:0;;34213:2:1;125056:45:0::3;::::0;::::3;34195:21:1::0;34252:1;34232:18;;;34225:29;-1:-1:-1;;;34270:18:1;;;34263:31;34311:18;;125056:45:0::3;34011:324:1::0;125056:45:0::3;125112:12;:28:::0;;125151:30;;-1:-1:-1;;;;;;;;125112:28:0;;::::3;::::0;;;::::3;-1:-1:-1::0;;;;125151:30:0;;;;;-1:-1:-1;;;125151:30:0;;::::3;::::0;;::::3;;::::0;;;125254:13:::3;::::0;:46:::3;::::0;-1:-1:-1;;;125254:46:0;;::::3;::::0;::::3;36277:50:1::0;;;;-1:-1:-1;;;;;125254:13:0::3;::::0;:30:::3;::::0;36250:18:1;;125254:46:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;-1:-1:-1::0;;125316:59:0::3;::::0;;-1:-1:-1;;;;;36563:15:1;;;36545:34;;36615:15;;36610:2;36595:18;;36588:43;125316:59:0::3;::::0;-1:-1:-1;36481:18:1;;-1:-1:-1;125316:59:0::3;36338:299:1::0;121142:154:0;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;121230:18;;::::1;::::0;:7:::1;::::0;:18:::1;::::0;::::1;::::0;::::1;:::i;:::-;;121264:24;121279:8;121264:24;;;;;;:::i;154907:126::-:0;154977:7;155004:21;155013:11;155004:8;:21::i;88170:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;140841:1853::-;4439:7;;;;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;141005:10:::1;141017:11;113502:39;113521:6;113529:11;113502:18;:39::i;:::-;113494:54;;;;-1:-1:-1::0;;;113494:54:0::1;;;;;;;:::i;:::-;141105:26:::2;141134::::0;;;:13:::2;:26;::::0;;;;;;;141105:55;;::::2;::::0;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;;::::2;::::0;;;;::::2;::::0;::::2;::::0;;;;;;;;::::2;;::::0;;;;;;141194:17:::2;:15;:17::i;:::-;141171:40;;;141225:21;141248:18:::0;141270:51:::2;141288:11;141301:9;141312:8;141270:17;:51::i;:::-;141224:97;;;;141336:10;141350:1;141336:15;141332:1355;;;141563:8;::::0;141536:24:::2;::::0;::::2;::::0;141575:15:::2;::::0;141536:35:::2;::::0;-1:-1:-1;;;141563:8:0;;::::2;-1:-1:-1::0;;;;;141563:8:0::2;::::0;141536:35:::2;:::i;:::-;:54;;141535:231;;;;;141752:13;141743:6;:22;141535:231;:283;;;;;141801:9;:16;;;141792:6;:25;141535:283;:815;;;;-1:-1:-1::0;142339:11:0::2;::::0;-1:-1:-1;;;142339:11:0;::::2;-1:-1:-1::0;;;;;142339:11:0::2;142313:22;142329:6:::0;142313:13;:22:::2;:::i;:::-;142312:38;;;;:::i;:::-;72459:5;142269:9;:25;;;:39;;;;:::i;:::-;:81;;141535:815;:924;;;;-1:-1:-1::0;142448:11:0::2;::::0;142419:16:::2;::::0;::::2;::::0;-1:-1:-1;;;142448:11:0;;::::2;-1:-1:-1::0;;;;;142448:11:0::2;::::0;142419:25:::2;::::0;142438:6;;142419:25:::2;:::i;:::-;142418:41;;;;:::i;:::-;72459:5;142375:9;:25;;;:39;;;;:::i;:::-;:84;;141535:924;141438:1059;;;::::0;-1:-1:-1;;;141438:1059:0;;34542:2:1;141438:1059:0::2;::::0;::::2;34524:21:1::0;34581:1;34561:18;;;34554:29;-1:-1:-1;;;34599:18:1;;;34592:32;34641:18;;141438:1059:0::2;34340:325:1::0;141438:1059:0::2;142512:26;::::0;;;:13:::2;:26;::::0;;;;:33:::2;;:43:::0;;142549:6;;142512:26;:43:::2;::::0;142549:6;;142512:43:::2;:::i;:::-;;;;;;;;142575:56;142592:11;142624:6;142605:9;:16;;;:25;;;;:::i;:::-;142575:56;::::0;;35658:25:1;;;35714:2;35699:18;;35692:34;;;;35631:18;142575:56:0::2;;;;;;;142648:27;142664:2;142668:6;142648:15;:27::i;:::-;141030:1664;;;;4734:1:::1;;140841:1853:::0;;;:::o;154621:161::-;154687:7;-1:-1:-1;;;;;154715:19:0;;154707:33;;;;-1:-1:-1;;;154707:33:0;;24314:2:1;154707:33:0;;;24296:21:1;24353:1;24333:18;;;24326:29;-1:-1:-1;;;24371:18:1;;;24364:31;24412:18;;154707:33:0;24112:324:1;154707:33:0;-1:-1:-1;;;;;;154758:16:0;;;;;:9;:16;;;;;;;154621:161::o;128819:150::-;128914:13;;-1:-1:-1;;;;;128914:13:0;128892:10;:36;128884:50;;;;-1:-1:-1;;;128884:50:0;;;;;;;:::i;:::-;128945:6;:16;;-1:-1:-1;;;;;;128945:16:0;-1:-1:-1;;;;;128945:16:0;;;;;;;;;;128819:150::o;143469:1159::-;4439:7;;;;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;143610:16:::1;143632:17;:15;:17::i;:::-;-1:-1:-1::0;143609:40:0;-1:-1:-1;143660:23:0::1;::::0;143694:810:::1;143718:12;:19;143714:1;:23;143694:810;;;143759:19;143781:12;143794:1;143781:15;;;;;;;;:::i;:::-;;;;;;;143759:37;;143815:20;143823:11;107732:4:::0;107756:20;;;:7;:20;;;;;;-1:-1:-1;;;;;107756:20:0;:34;;;107671:127;143815:20:::1;143811:682;;;143899:26;143928::::0;;;:13:::1;:26;::::0;;;;;;;143899:55;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;;::::0;;;;;;:26;144019:51:::1;143942:11:::0;143899:55;144061:8;144019:17:::1;:51::i;:::-;143973:97;;;;144093:10;144107:1;144093:15;144089:389;;;144414:44;144444:13;144414:29;:44::i;:::-;144395:63;::::0;;::::1;:::i;:::-;;;144089:389;143837:656;;;143811:682;-1:-1:-1::0;143739:3:0;::::1;::::0;::::1;:::i;:::-;;;;143694:810;;;-1:-1:-1::0;144519:46:0::1;::::0;;144537:10:::1;20115:74:1::0;;20220:2;20205:18;;20198:34;;;144519:46:0::1;::::0;20088:18:1;144519:46:0::1;;;;;;;144576:44;144592:10;144604:15;144576;:44::i;123777:494::-:0;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;123965:8:::1;123975;75480:6;:13;75463:6;:13;:30;:51;;;;;75513:1;75497:6;:13;:17;75463:51;75455:65;;;::::0;-1:-1:-1;;;75455:65:0;;32814:2:1;75455:65:0::1;::::0;::::1;32796:21:1::0;32853:1;32833:18;;;32826:29;-1:-1:-1;;;32871:18:1;;;32864:31;32912:18;;75455:65:0::1;32612:324:1::0;75455:65:0::1;75536:9;75531:257;75572:1;75556:6;:13;:17;;;;:::i;:::-;75551:1;:22;75531:257;;72459:5;-1:-1:-1::0;;;;;75603:32:0::1;:6;75610:1;75603:9;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75603:32:0::1;;;:68;;;;;72459:5;-1:-1:-1::0;;;;;75639:32:0::1;:6;75646:1;75639:9;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75639:32:0::1;;;75603:68;75595:82;;;::::0;-1:-1:-1;;;75595:82:0;;33884:2:1;75595:82:0::1;::::0;::::1;33866:21:1::0;33923:1;33903:18;;;33896:29;-1:-1:-1;;;33941:18:1;;;33934:31;33982:18;;75595:82:0::1;33682:324:1::0;75595:82:0::1;75696:5:::0;;75692:85:::1;;75742:6:::0;75749:5:::1;75753:1;75749::::0;:5:::1;:::i;:::-;75742:13;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75730:25:0::1;:6;75737:1;75730:9;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;75730:25:0::1;;75722:39;;;::::0;-1:-1:-1;;;75722:39:0;;26342:2:1;75722:39:0::1;::::0;::::1;26324:21:1::0;26381:1;26361:18;;;26354:29;-1:-1:-1;;;26399:18:1;;;26392:31;26440:18;;75722:39:0::1;26140:324:1::0;75722:39:0::1;75575:3:::0;::::1;::::0;::::1;:::i;:::-;;;;75531:257;;;;124000:7:::2;:12;;124011:1;124000:12;123996:210;;;124029:25:::0;;::::2;::::0;:14:::2;::::0;:25:::2;::::0;::::2;::::0;::::2;:::i;:::-;-1:-1:-1::0;124069:25:0;;::::2;::::0;:14:::2;::::0;:25:::2;::::0;::::2;::::0;::::2;:::i;:::-;;123996:210;;;124127:26:::0;;::::2;::::0;:15:::2;::::0;:26:::2;::::0;::::2;::::0;::::2;:::i;:::-;-1:-1:-1::0;124168:26:0;;::::2;::::0;:15:::2;::::0;:26:::2;::::0;::::2;::::0;::::2;:::i;:::-;;123996:210;124221:42;124235:8;124245;124255:7;124221:42;;;;;;;;:::i;:::-;;;;;;;;44361:1:::1;;123777:494:::0;;;;:::o;119548:86::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;119618:8:::1;:6;:8::i;118173:232::-:0;113726:19;;-1:-1:-1;;;;;113726:19:0;113712:10;:33;113704:47;;;;-1:-1:-1;;;113704:47:0;;;;;;;:::i;:::-;118291:19:::1;:42:::0;;-1:-1:-1;;;;;;118291:42:0::1;-1:-1:-1::0;;;;;118291:42:0;::::1;::::0;;::::1;::::0;;;118349:48:::1;::::0;::::1;::::0;-1:-1:-1;;118349:48:0::1;118173:232:::0;:::o;156350:260::-;-1:-1:-1;;;;;156447:22:0;;156459:10;156447:22;;156439:37;;;;-1:-1:-1;;;156439:37:0;;26012:2:1;156439:37:0;;;25994:21:1;26051:1;26031:18;;;26024:29;-1:-1:-1;;;26069:18:1;;;26062:32;26111:18;;156439:37:0;25810:325:1;156439:37:0;156506:10;156487:30;;;;:18;:30;;;;;;;-1:-1:-1;;;;;156487:40:0;;;;;;;;;;:51;;-1:-1:-1;;156487:51:0;;;;;;;:40;-1:-1:-1;;;;;156554:48:0;;156593:8;156554:48;;;;22924:14:1;22917:22;22899:41;;22887:2;22872:18;;22759:187;156554:48:0;;;;;;;;156350:260;;:::o;133487:2628::-;133721:19;4694:8;4439:7;;;;;4368:86;4694:8;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;133705:5;-1:-1:-1;;;;;76413:24:0;::::1;76405:38;;;::::0;-1:-1:-1;;;76405:38:0;;24314:2:1;76405:38:0::1;::::0;::::1;24296:21:1::0;24353:1;24333:18;;;24326:29;-1:-1:-1;;;24371:18:1;;;24364:31;24412:18;;76405:38:0::1;24112:324:1::0;76405:38:0::1;133842:1:::2;133824:15;:19;133816:34;;;::::0;-1:-1:-1;;;133816:34:0;;27078:2:1;133816:34:0::2;::::0;::::2;27060:21:1::0;27117:1;27097:18;;;27090:29;-1:-1:-1;;;27135:18:1;;;27128:32;27177:18;;133816:34:0::2;26876:325:1::0;133816:34:0::2;134163:11;::::0;134119:6:::2;::::0;:65:::2;::::0;-1:-1:-1;;;;;134119:6:0;;::::2;::::0;134143:10:::2;::::0;134163:11:::2;134177:6:::0;134119:23:::2;:65::i;:::-;134347:14;134365:17;:15;:17::i;:::-;134344:38;;;134599:13;134589:6;:23;;134581:38;;;::::0;-1:-1:-1;;;134581:38:0;;30808:2:1;134581:38:0::2;::::0;::::2;30790:21:1::0;30847:1;30827:18;;;30820:29;-1:-1:-1;;;30865:18:1;;;30858:32;30907:18;;134581:38:0::2;30606:325:1::0;134581:38:0::2;134741:30;134803:11:::0;;134775:24:::2;134793:6:::0;134775:15;:24:::2;:::i;:::-;134774:40;;;;:::i;:::-;134741:73;;134907:17;134927:62;134941:6;134949:22;134973:15;134927:13;:62::i;:::-;134907:82;;135021:12;135008:9;:25;;135000:40;;;::::0;-1:-1:-1;;;135000:40:0;;28743:2:1;135000:40:0::2;::::0;::::2;28725:21:1::0;28782:1;28762:18;;;28755:29;-1:-1:-1;;;28800:18:1;;;28793:32;28842:18;;135000:40:0::2;28541:325:1::0;135000:40:0::2;135184:11;::::0;:23:::2;::::0;135198:9;;-1:-1:-1;;;135184:11:0;::::2;-1:-1:-1::0;;;;;135184:11:0::2;:23;:::i;:::-;135150:29;72459:5;135150:15:::0;:29:::2;:::i;:::-;135149:58;;135141:73;;;::::0;-1:-1:-1;;;135141:73:0;;31797:2:1;135141:73:0::2;::::0;::::2;31779:21:1::0;31836:1;31816:18;;;31809:29;-1:-1:-1;;;31854:18:1;;;31847:32;31896:18;;135141:73:0::2;31595:325:1::0;135141:73:0::2;135252:29;:17;21806:19:::0;;21824:1;21806:19;;;21717:127;135252:29:::2;135306:17;21687:14:::0;135292:41:::2;;135476:29;135490:11;135503:1;135476:13;:29::i;:::-;135632:22;135612:16;;:42;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;135696:62:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;135714:15:::2;135696:62;::::0;;::::2;::::0;;;;;;;;;;;;;;;-1:-1:-1;135667:26:0;;;:13:::2;:26:::0;;;;;;;:91;;;;;;::::2;::::0;::::2;::::0;;::::2;::::0;::::2;::::0;;;::::2;::::0;;::::2;::::0;136002:25:::2;136008:5:::0;135681:11;136002:5:::2;:25::i;:::-;136043:64;::::0;;35968:25:1;;;36024:2;36009:18;;36002:34;;;36052:18;;;36045:34;;;36110:2;36095:18;;36088:34;;;136043:64:0::2;::::0;35955:3:1;35940:19;136043:64:0::2;;;;;;;133742:2373;;;4734:1:::1;133487:2628:::0;;;;;;;:::o;114512:575::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;114733:9:::1;114728:119;114752:12;:19;114748:1;:23;114728:119;;;114793:42;-1:-1:-1::0;;;;;;;;;;;114819:12:0::1;114832:1;114819:15;;;;;;;;:::i;:::-;;;;;;;114793:10;:42::i;:::-;114773:3:::0;::::1;::::0;::::1;:::i;:::-;;;;114728:119;;;;114921:35;-1:-1:-1::0;;;;;;;;;;;114947:8:0::1;114921:10;:35::i;:::-;115001:13;::::0;114967:49:::1;::::0;-1:-1:-1;;;;;;;;;;;112786:26:0;-1:-1:-1;;;;;115001:13:0::1;114967:10;:49::i;:::-;-1:-1:-1::0;115027:11:0::1;:25:::0;;-1:-1:-1;;;;;115027:25:0;;::::1;-1:-1:-1::0;;;;;;115027:25:0;;::::1;;::::0;;;115063:6:::1;:16:::0;;;;;::::1;::::0;::::1;;::::0;;-1:-1:-1;;114512:575:0:o;125633:358::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;125805:27:::1;72459:5;76078:4;-1:-1:-1::0;;;;;76078:19:0::1;;;76070:33;;;::::0;-1:-1:-1;;;76070:33:0;;25353:2:1;76070:33:0::1;::::0;::::1;25335:21:1::0;25392:1;25372:18;;;25365:29;-1:-1:-1;;;25410:18:1;;;25403:31;25451:18;;76070:33:0::1;25151:324:1::0;76070:33:0::1;125850:26:::2;:56:::0;;-1:-1:-1;;;;;125850:56:0::2;-1:-1:-1::0;;;;;;;;125850:56:0;;::::2;::::0;::::2;::::0;;;::::2;::::0;;;;125922:61:::2;::::0;125956:26;::::2;;36277:50:1::0;;125922:61:0::2;::::0;36265:2:1;36250:18;125922:61:0::2;36133:200:1::0;158374:259:0;158546:10;158558:11;113502:39;113521:6;113529:11;113502:18;:39::i;:::-;113494:54;;;;-1:-1:-1;;;113494:54:0;;;;;;;:::i;:::-;158582:43:::1;158596:4;158602:2;158606:11;158619:5;158582:13;:43::i;:::-;158374:259:::0;;;;;;:::o;145393:6026::-;4439:7;;;;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;145624:16:::1;145642:14:::0;145660:17:::1;:15;:17::i;:::-;145623:54;;;;145774:19;145796:13;;;;;;;;;-1:-1:-1::0;;;;;145796:13:0::1;-1:-1:-1::0;;;;;145796:28:0::1;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;145880:13;::::0;145774:52;;-1:-1:-1;145837:25:0::1;::::0;72459:5:::1;::::0;145866:27:::1;::::0;-1:-1:-1;;;145880:13:0;::::1;-1:-1:-1::0;;;;;145880:13:0::1;145774:52:::0;145866:27:::1;:::i;:::-;145865:43;;;;:::i;:::-;146040:12;::::0;145837:71;;-1:-1:-1;72459:5:0::1;::::0;146026:26:::1;::::0;-1:-1:-1;;;146040:12:0;::::1;-1:-1:-1::0;;;;;146040:12:0::1;146026:11:::0;:26:::1;:::i;:::-;146025:42;;;;:::i;:::-;146006:16;;:61;145998:76;;;::::0;-1:-1:-1;;;145998:76:0;;29073:2:1;145998:76:0::1;::::0;::::1;29055:21:1::0;29112:1;29092:18;;;29085:29;-1:-1:-1;;;29130:18:1;;;29123:32;29172:18;;145998:76:0::1;28871:325:1::0;145998:76:0::1;146085:23;146119:19:::0;146206:26:::1;146247:12;:19;-1:-1:-1::0;;;;;146235:32:0::1;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;;;;;;;;;146235:32:0::1;;;;;;;;;;;;;;;;146206:61;;146285:9;146280:2801;146304:12;:19;146300:1;:23;146280:2801;;;146345:19;146367:12;146380:1;146367:15;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;146397:13:::1;146413:20:::0;;;:7:::1;:20:::0;;;;;;;;146367:15;;-1:-1:-1;;;;;;146413:20:0::1;146452:19:::0;;146448:2622:::1;;146564:26;146593::::0;;;:13:::1;:26;::::0;;;;;;;146564:55;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;;::::0;;;;;;:26;146761:51:::1;146607:11:::0;146564:55;146803:8;146761:17:::1;:51::i;:::-;146715:97;;;;146835:10;146849:1;146835:15;146831:2070;;;147325:44;147355:13;147325:29;:44::i;:::-;147306:63;::::0;;::::1;:::i;:::-;;;146831:2070;;;147426:8;::::0;147399:24:::1;::::0;::::1;::::0;147438:15:::1;::::0;147399:35:::1;::::0;-1:-1:-1;;;147426:8:0;;::::1;-1:-1:-1::0;;;;;147426:8:0::1;::::0;147399:35:::1;:::i;:::-;:54;147395:1506;;147810:39;147826:11;147839:9;147810:15;:39::i;:::-;147872:23;148032:16;;148012:17;:36;148008:267;;;148138:17;72459:5;148104:16;;:30;;;;:::i;:::-;148103:52;;;;:::i;:::-;148077:79;;148008:267;;;-1:-1:-1::0;72459:5:0::1;148008:267;148396:24;148422:12:::0;148438:178:::1;148485:13;148525:9;:25;;;148577:16;148438:20;:178::i;:::-;148395:221:::0;;-1:-1:-1;148395:221:0;-1:-1:-1;148639:19:0::1;148395:221:::0;148639:19;::::1;:::i;:::-;;;148851:30;;;;;;;;148857:5;-1:-1:-1::0;;;;;148851:30:0::1;;;;;148864:16;148851:30;;::::0;148834:11:::1;148846:1;148834:14;;;;;;;;:::i;:::-;;;;;;:47;;;;147455:1446;;;147395:1506;149030:17;149010:16;;:37;149006:48;;149049:5;;;;;;;149006:48;146473:2597;;;146448:2622;146330:2751;;146325:3;;;;;:::i;:::-;;;;146280:2801;;;-1:-1:-1::0;149093:12:0::1;149109:22:::0;;149108:123:::1;;149208:21;149212:17:::0;149208:1:::1;:21;:::i;:::-;72459:5;149173:16;;:30;;;;:::i;:::-;149172:58;;;;:::i;:::-;149108:123;;;149148:1;149108:123;149093:138;;72459:5;149755:63;149772:5;149779:18;149755:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;149755:63:0::1;-1:-1:-1::0;;;;;149755:63:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149799:18;149755:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;149755:63:0::1;-1:-1:-1::0;;;;;149755:63:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:16;:63::i;:::-;149741:77;::::0;-1:-1:-1;;;;;149741:77:0::1;:11:::0;:77:::1;:::i;:::-;149740:93;;;;:::i;:::-;149726:107;;149969:20;;149955:11;:34;:71;;150006:20;;149955:71;;;149992:11;149955:71;149941:85:::0;-1:-1:-1;150707:21:0::1;72459:5;150812:14;:6:::0;150821:5:::1;150812:14;:::i;:::-;:28;;;;:::i;:::-;150783:11;::::0;150752:13:::1;::::0;150769:11;;150737:28:::1;::::0;-1:-1:-1;;;;;;;;150752:13:0;::::1;::::0;::::1;::::0;-1:-1:-1;;;150737:12:0;::::1;;:28;:::i;:::-;150732:34;::::0;:1:::1;:34;:::i;:::-;-1:-1:-1::0;;;;;150732:48:0::1;;;;;:::i;:::-;:62;;;;:::i;:::-;150731:110;;;;:::i;:::-;150707:134;;150880:13;150866:11;:27;:57;;150910:13;150866:57;;;150896:11;150866:57;150852:71:::0;-1:-1:-1;150941:91:0::1;150963:12:::0;150977:11;150990:10:::1;151002:29;151016:15:::0;150852:71;151002:29:::1;:::i;:::-;150941:91;;;;;;;;;:::i;:::-;;;;;;;;151126:9;151121:222;151145:12;:19;151141:1;:23;151121:222;;;151224:1;151190:11;151202:1;151190:14;;;;;;;;:::i;:::-;;;;;;;:31;;;:35;151186:146;;;151246:70;151262:11;151274:1;151262:14;;;;;;;;:::i;:::-;;;;;;;:20;;;151284:11;151296:1;151284:14;;;;;;;;:::i;:::-;;;;;;;:31;;;151246:15;:70::i;:::-;151166:3:::0;::::1;::::0;::::1;:::i;:::-;;;;151121:222;;;-1:-1:-1::0;151353:58:0::1;151369:10;151381:29;151395:15:::0;151381:11;:29:::1;:::i;:::-;151353:15;:58::i;:::-;145486:5933;;;;;;;;;145393:6026:::0;:::o;82847:30::-;;;;;;;;;;;;118949:234;119069:11;;-1:-1:-1;;;;;119069:11:0;119047:10;:34;119039:48;;;;-1:-1:-1;;;119039:48:0;;;;;;;:::i;:::-;119098:19;:32;;-1:-1:-1;;;;;119141:34:0;;;-1:-1:-1;;;119141:34:0;-1:-1:-1;;;;;;119141:34:0;;;119098:32;;;;119141:34;;;;;;;;;;118949:234::o;153695:752::-;107732:4;107756:20;;;:7;:20;;;;;;153766:13;;-1:-1:-1;;;;;107756:20:0;153792:34;;;;-1:-1:-1;;;153792:34:0;;31468:2:1;153792:34:0;;;31450:21:1;31507:1;31487:18;;;31480:29;-1:-1:-1;;;31525:18:1;;;31518:31;31566:18;;153792:34:0;31266:324:1;153792:34:0;153983:11;153968:12;154030:78;154037:9;;154030:78;;154063:8;;;;:::i;:::-;;-1:-1:-1;154086:10:0;;-1:-1:-1;154094:2:0;154086:10;;:::i;:::-;;;154030:78;;;154118:19;154150:6;-1:-1:-1;;;;;154140:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;154140:17:0;;154118:39;;154168:172;154175:16;;154168:172;;154208:11;154218:1;154208:11;;:::i;:::-;;-1:-1:-1;154277:16:0;154291:2;154277:11;:16;:::i;:::-;154264:30;;:2;:30;:::i;:::-;154251:45;;154234:6;154241;154234:14;;;;;;;;:::i;:::-;;;;:62;-1:-1:-1;;;;;154234:62:0;;;;;;;;-1:-1:-1;154311:17:0;154326:2;154311:17;;:::i;:::-;;;154168:172;;;154381:1;154363:7;154357:21;;;;;:::i;:::-;;;:25;:82;;;;;;;;;;;;;;;;;154409:7;154425:6;154392:41;;;;;;;;;:::i;:::-;;;;;;;;;;;;;154357:82;154350:89;153695:752;-1:-1:-1;;;;;153695:752:0:o;87491:34::-;;;;;;;;;;;;46370:143;45665:7;45692:12;;;:6;:12;;;;;:22;;;44322:28;44333:4;44339:10;44322;:28::i;:::-;46479:26:::1;46491:4;46497:7;46479:11;:26::i;83317:31::-:0;;;;;;;;;;;;151975:237;152068:7;152126:26;;;:13;:26;;;;;;;;152097:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;152068:7;;152170:34;152097:55;152199:4;152170:17;:34::i;:::-;152163:41;;;;;151975:237;;;;;:::o;120545:378::-;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;120702:20;-1:-1:-1;;;;;76413:24:0;::::1;76405:38;;;::::0;-1:-1:-1;;;76405:38:0;;24314:2:1;76405:38:0::1;::::0;::::1;24296:21:1::0;24353:1;24333:18;;;24326:29;-1:-1:-1;;;24371:18:1;;;24364:31;24412:18;;76405:38:0::1;24112:324:1::0;76405:38:0::1;120740:15:::2;:34:::0;;;120785:19:::2;:42:::0;;-1:-1:-1;;;;;;120785:42:0::2;-1:-1:-1::0;;;;;120785:42:0;::::2;::::0;;::::2;::::0;;;120843:72:::2;::::0;23097:25:1;;;120843:72:0::2;::::0;23085:2:1;23070:18;120843:72:0::2;;;;;;;;44361:1:::1;120545:378:::0;;;:::o;137188:1759::-;4439:7;;;;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;137357:10:::1;137369:11;113502:39;113521:6;113529:11;113502:18;:39::i;:::-;113494:54;;;;-1:-1:-1::0;;;113494:54:0::1;;;;;;;:::i;:::-;137457:26:::2;137486::::0;;;:13:::2;:26;::::0;;;;;;;137457:55;;::::2;::::0;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;;::::2;::::0;;;;::::2;::::0;::::2;::::0;;;;;;;;::::2;;::::0;;;;;;137546:17:::2;:15;:17::i;:::-;137523:40;;;137781:21;137804:18:::0;137826:51:::2;137844:11;137857:9;137868:8;137826:17;:51::i;:::-;137780:97;;;;137892:10;137906:1;137892:15;137888:1052;;;138065:8;::::0;138038:24:::2;::::0;::::2;::::0;138077:15:::2;::::0;138038:35:::2;::::0;-1:-1:-1;;;138065:8:0;;::::2;-1:-1:-1::0;;;;;138065:8:0::2;::::0;138038:35:::2;:::i;:::-;:54;;138030:69;;;::::0;-1:-1:-1;;;138030:69:0;;30478:2:1;138030:69:0::2;::::0;::::2;30460:21:1::0;30517:1;30497:18;;;30490:29;-1:-1:-1;;;30535:18:1;;;30528:32;30577:18;;138030:69:0::2;30276:325:1::0;138030:69:0::2;138167:39;138183:11;138196:9;138167:15;:39::i;:::-;138340:24;138370:374;138409:13;138441:9;:25;;;138693:36;138712:16;;138693:18;:36::i;:::-;138370:20;:374::i;:::-;138339:405;;;138787:16;138767;:36;;138759:51;;;::::0;-1:-1:-1;;;138759:51:0;;30148:2:1;138759:51:0::2;::::0;::::2;30130:21:1::0;30187:1;30167:18;;;30160:29;-1:-1:-1;;;30205:18:1;;;30198:32;30247:18;;138759:51:0::2;29946:325:1::0;138759:51:0::2;138830:46;::::0;;35658:25:1;;;35714:2;35699:18;;35692:34;;;138830:46:0::2;::::0;35631:18:1;138830:46:0::2;;;;;;;138891:37;138907:2;138911:16;138891:15;:37::i;122339:496::-:0;-1:-1:-1;;;;;;;;;;;44322:28:0;44333:4;44339:10;44322;:28::i;:::-;122512:18:::1;72459:5;76078:4;-1:-1:-1::0;;;;;76078:19:0::1;;;76070:33;;;::::0;-1:-1:-1;;;76070:33:0;;25353:2:1;76070:33:0::1;::::0;::::1;25335:21:1::0;25392:1;25372:18;;;25365:29;-1:-1:-1;;;25410:18:1;;;25403:31;25451:18;;76070:33:0::1;25151:324:1::0;76070:33:0::1;122630::::2;122645:18:::0;122630:12;:33:::2;:::i;:::-;-1:-1:-1::0;;;;;122613:50:0::2;:14;122626:1;72459:5;122613:14;:::i;:::-;:50;122605:64;;;::::0;-1:-1:-1;;;122605:64:0;;34213:2:1;122605:64:0::2;::::0;::::2;34195:21:1::0;34252:1;34232:18;;;34225:29;-1:-1:-1;;;34270:18:1;;;34263:31;34311:18;;122605:64:0::2;34011:324:1::0;122605:64:0::2;122680:11;:26:::0;;-1:-1:-1;;;;;;122717:38:0;-1:-1:-1;;;;;;;;122680:26:0;;::::2;::::0;;::::2;-1:-1:-1::0;;122717:38:0;;;;;;;::::2;::::0;;::::2;::::0;;;122771:56:::2;::::0;;36545:34:1;;;36610:2;36595:18;;36588:43;;;;122771:56:0::2;::::0;36481:18:1;122771:56:0::2;;;;;;;44361:1:::1;122339:496:::0;;;:::o;105728:168::-;105790:13;105824:20;;;:7;:20;;;;;;-1:-1:-1;;;;;105824:20:0;105863:19;105855:33;;;;-1:-1:-1;;;105855:33:0;;31468:2:1;105855:33:0;;;31450:21:1;31507:1;31487:18;;;31480:29;-1:-1:-1;;;31525:18:1;;;31518:31;31566:18;;105855:33:0;31266:324:1;105855:33:0;105728:168;;;:::o;110235:180::-;110306:32;;;;:19;:32;;;;;:37;;-1:-1:-1;;;;;;110306:37:0;-1:-1:-1;;;;;110306:37:0;;;;;;;;:32;;110368:21;110306:32;110368:8;:21::i;:::-;-1:-1:-1;;;;;110359:48:0;;;;;;;;;;;110235:180;;:::o;34436:211::-;34580:58;;-1:-1:-1;;;;;20133:55:1;;34580:58:0;;;20115:74:1;20205:18;;;20198:34;;;34553:86:0;;34573:5;;-1:-1:-1;;;34603:23:0;20088:18:1;;34580:58:0;;;;-1:-1:-1;;34580:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;34580:58:0;-1:-1:-1;;;;;;34580:58:0;;;;;;;;;;34553:19;:86::i;107923:322::-;108012:4;108086:13;108102:21;108111:11;108102:8;:21::i;:::-;108086:37;;108153:5;-1:-1:-1;;;;;108142:16:0;:7;-1:-1:-1;;;;;108142:16:0;;:56;;;-1:-1:-1;106142:7:0;106169:32;;;:19;:32;;;;;;-1:-1:-1;;;;;108162:36:0;;;106169:32;;108162:36;108142:56;:94;;;-1:-1:-1;;;;;;108202:25:0;;;;;;;:18;:25;;;;;;;:34;;;;;;;;;;;;108142:94;108134:103;107923:322;-1:-1:-1;;;;107923:322:0:o;102714:1018::-;102790:33;102804:11;102817:5;102790:13;:33::i;:::-;102834:14;102851:20;;;:7;:20;;;;;;102886:10;;102882:843;;102936:1;102913:20;;;:7;:20;;;;;;;;:24;;;102968:7;:20;;;;;;103629:11;;-1:-1:-1;;;;;102968:20:0;;;;103629:39;;:11;102968:20;103661:6;103629:24;:39::i;:::-;103699:5;-1:-1:-1;;;;;103688:25:0;;103706:6;103688:25;;;;23097::1;;23085:2;23070:18;;22951:177;109710:458:0;109863:4;-1:-1:-1;;;;;109838:29:0;:21;109847:11;109838:8;:21::i;:::-;-1:-1:-1;;;;;109838:29:0;;109830:43;;;;-1:-1:-1;;;109830:43:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;109892:16:0;;109884:31;;;;-1:-1:-1;;;109884:31:0;;31138:2:1;109884:31:0;;;31120:21:1;31177:1;31157:18;;;31150:29;-1:-1:-1;;;31195:18:1;;;31188:32;31237:18;;109884:31:0;30936:325:1;109884:31:0;109980:33;109997:1;110001:11;109980:8;:33::i;:::-;-1:-1:-1;;;;;110026:15:0;;;;;;:9;:15;;;;;:20;;110045:1;;110026:15;:20;;110045:1;;110026:20;:::i;:::-;;;;-1:-1:-1;;;;;;;110057:13:0;;;;;;:9;:13;;;;;:18;;110074:1;;110057:13;:18;;110074:1;;110057:18;:::i;:::-;;;;-1:-1:-1;;110086:20:0;;;;:7;:20;;;;;;:25;;-1:-1:-1;;;;;;110086:25:0;-1:-1:-1;;;;;110086:25:0;;;;;;;;;110129:31;;110086:20;;110129:31;;;;;;;109710:458;;;:::o;95497:110::-;95583:6;;:16;;;-1:-1:-1;;;95583:16:0;;;;95547:7;;;;-1:-1:-1;;;;;95583:6:0;;;;:14;;:16;;;;;;;;;;;:6;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95576:23;;;;95497:110;;:::o;92670:593::-;92816:7;92825;92845:18;92875:21;92898:30;92932:38;92950:9;92961:8;92932:17;:38::i;:::-;92874:96;;;;92985:13;93002:1;92985:18;:49;;;;93007:22;93033:1;93007:27;92985:49;92981:230;;;93051:39;93067:11;93080:9;93051:15;:39::i;:::-;93198:1;93185:14;;92981:230;-1:-1:-1;93229:13:0;-1:-1:-1;93244:10:0;-1:-1:-1;92670:593:0;;;;;;;:::o;34655:248::-;34826:68;;-1:-1:-1;;;;;19292:15:1;;;34826:68:0;;;19274:34:1;19344:15;;19324:18;;;19317:43;19376:18;;;19369:34;;;34799:96:0;;34819:5;;-1:-1:-1;;;34849:27:0;19186:18:1;;34826:68:0;19011:398:1;34799:96:0;34655:248;;;;:::o;44891:519::-;44540:4;44564:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;44564:29:0;;;;;;;;;;;;44967:436;;45160:52;45199:7;-1:-1:-1;;;;;45160:52:0;45209:2;45160:30;:52::i;:::-;45285:49;45324:4;45331:2;45285:30;:49::i;:::-;45065:292;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;45065:292:0;;;;;;;;;;-1:-1:-1;;;45011:380:0;;;;;;;:::i;48199:228::-;44540:4;44564:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;44564:29:0;;;;;;;;;;;;48270:150;;48314:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;48314:29:0;;;;;;;;;;:36;;-1:-1:-1;;48314:36:0;48346:4;48314:36;;;48370:38;48397:10;;48321:4;;48370:38;;48314:12;48370:38;48199:228;;:::o;48435:229::-;44540:4;44564:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;44564:29:0;;;;;;;;;;;;48507:150;;;48582:5;48550:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;48550:29:0;;;;;;;;;;:37;;-1:-1:-1;;48550:37:0;;;48607:38;48634:10;;48557:4;;48607:38;;48582:5;48607:38;48435:229;;:::o;101881:332::-;101931:7;101955:16;;101975:1;101955:21;101951:81;;;-1:-1:-1;102000:20:0;;;101881:332::o;101951:81::-;102189:16;;72255:6;102148:10;;102130:14;;102100:27;:25;:27::i;:::-;:44;;;;:::i;:::-;102099:59;;;;:::i;:::-;:73;;;;:::i;:::-;102098:107;;;;:::i;:::-;102062:20;;:143;;;;:::i;:::-;102042:163;;101881:332;:::o;5427:120::-;4439:7;;;;4963:41;;;;-1:-1:-1;;;4963:41:0;;25004:2:1;4963:41:0;;;24986:21:1;25043:2;25023:18;;;25016:30;-1:-1:-1;;;25062:18:1;;;25055:50;25122:18;;4963:41:0;24802:344:1;4963:41:0;5486:7:::1;:15:::0;;-1:-1:-1;;5486:15:0::1;::::0;;5517:22:::1;2877:10:::0;5526:12:::1;5517:22;::::0;-1:-1:-1;;;;;18944:55:1;;;18926:74;;18914:2;18899:18;5517:22:0::1;;;;;;;5427:120::o:0;4037:131::-;1592:13;;;;;;;;:30;;-1:-1:-1;1610:12:0;;;;1609:13;1592:30;1584:89;;;;-1:-1:-1;;;1584:89:0;;;;;;;:::i;:::-;1709:13;;;;;;;1708:14;1733:101;;;;1768:13;:20;;-1:-1:-1;;1803:19:0;;;;;1733:101;4096:26:::1;:24;:26::i;:::-;4133:27;:25;:27::i;:::-;1864:14:::0;1860:68;;;1895:13;:21;;-1:-1:-1;;1895:21:0;;;1573:362;4037:131::o;42378:104::-;1592:13;;;;;;;;:30;;-1:-1:-1;1610:12:0;;;;1609:13;1592:30;1584:89;;;;-1:-1:-1;;;1584:89:0;;;;;;;:::i;:::-;1709:13;;;;;;;1708:14;1733:101;;;;1768:13;:20;;-1:-1:-1;;1803:19:0;;;;;1733:101;42442:32:::1;:30;:32::i;47768:104::-:0;47839:25;47850:4;47856:7;47839:10;:25::i;48004:187::-;45665:7;45692:12;;;:6;:12;;;;;:22;;;48128:9;;48085:53;;48102:4;;48085:53;;;;;48149:12;;;;:6;:12;;;;;;:22;;:34;48004:187::o;5168:118::-;4439:7;;;;4693:9;4685:38;;;;-1:-1:-1;;;4685:38:0;;;;;;;:::i;:::-;5228:7:::1;:14:::0;;-1:-1:-1;;5228:14:0::1;5238:4;5228:14;::::0;;5258:20:::1;5265:12;2877:10:::0;;2797:98;104384:286;104460:7;104642:20;;;:7;:20;;;;;;;;;104615:11;;104530:27;:40;;;;;;;104642:20;;104615:11;72255:6;;104510:17;:15;:17::i;:::-;:60;;;;:::i;:::-;104501:70;;:5;:70;:::i;:::-;104500:99;;;;:::i;:::-;:126;;;;:::i;:::-;:162;;;;:::i;91208:796::-;91305:11;;:24;;;-1:-1:-1;;;91305:24:0;;;;91284:18;;-1:-1:-1;;;;;91305:11:0;;:22;;:24;;;;;;;;;;;;;;:11;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91284:45;;91358:6;91344:10;:20;;:34;;;;;91377:1;91368:6;:10;91344:34;91340:657;;;91506:11;;91474:6;;:60;;-1:-1:-1;;;;;91474:6:0;;;;91506:11;91520:5;91527:6;91474:23;:60::i;91340:657::-;91556:10;;91552:445;;91806:18;91827:19;91836:10;91827:6;:19;:::i;:::-;91893:11;;91861:6;;91806:40;;-1:-1:-1;91861:64:0;;-1:-1:-1;;;;;91861:6:0;;;;91893:11;91907:5;91914:10;91861:23;:64::i;:::-;91940:13;;:45;;-1:-1:-1;;;91940:45:0;;;;;35356:25:1;;;-1:-1:-1;;;;;35417:55:1;;;35397:18;;;35390:83;91940:13:0;;;;:26;;35329:18:1;;91940:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91568:429;91273:731;91208:796;;:::o;96251:296::-;96397:26;;96336:18;;72459:5;;96381:42;;-1:-1:-1;;;96397:26:0;;-1:-1:-1;;;;;96397:26:0;96381:13;:42;:::i;:::-;96380:58;;;;:::i;:::-;96367:71;;96475:24;;96462:10;:37;:77;;96515:24;;96462:77;;98122:1297;98275:17;98573:12;98588:61;98626:22;98607:16;;:41;;;;:::i;:::-;98588:18;:61::i;:::-;98573:76;-1:-1:-1;72459:5:0;-1:-1:-1;;;;;98668:27:0;;;98660:42;;;;-1:-1:-1;;;98660:42:0;;29818:2:1;98660:42:0;;;29800:21:1;29857:1;29837:18;;;29830:29;-1:-1:-1;;;29875:18:1;;;29868:32;29917:18;;98660:42:0;29616:325:1;98660:42:0;98912:21;72459:5;98959:55;98976:5;98983:14;98959:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;98959:55:0;-1:-1:-1;;;;;98959:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98999:14;98959:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;98959:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;:16;:55::i;:::-;98937:19;;:77;;;-1:-1:-1;;;;;98937:19:0;:77;:::i;:::-;-1:-1:-1;;;;;98936:106:0;;;;;:::i;:::-;98912:130;-1:-1:-1;72459:5:0;99169:27;98912:130;72459:5;99169:27;:::i;:::-;99150:47;;:15;:47;:::i;:::-;99149:63;;;;:::i;:::-;99131:81;;:15;:81;:::i;:::-;99115:97;-1:-1:-1;99389:22:0;99115:97;99389:6;:22;:::i;:::-;99377:34;98122:1297;-1:-1:-1;;;;;;98122:1297:0:o;105004:477::-;105106:17;:15;:17::i;:::-;105083:20;:40;105151:27;:25;:27::i;:::-;105134:14;:44;105372:27;105380:11;105393:5;105372:7;:27::i;:::-;105349:20;;;;:7;:20;;;;;;;;:50;;;;105453:20;;105410:27;:40;;;;;:63;;;;-1:-1:-1;105004:477:0:o;108693:264::-;-1:-1:-1;;;;;108761:13:0;;;;;;:9;:13;;;;;:18;;108778:1;;108761:13;:18;;108778:1;;108761:18;:::i;:::-;;;;-1:-1:-1;;108790:20:0;;;;:7;:20;;;;;;:25;;-1:-1:-1;;;;;;108790:25:0;-1:-1:-1;;;;;108790:25:0;;;;;;;;108831:37;;108790:20;;;108831:37;;108790:20;;108831:37;108887:55;108918:1;108922:2;108926:11;108887:55;;;;;;;;;;;;:22;:55::i;:::-;108879:70;;;;-1:-1:-1;;;108879:70:0;;27738:2:1;108879:70:0;;;27720:21:1;27777:1;27757:18;;;27750:29;-1:-1:-1;;;27795:18:1;;;27788:32;27837:18;;108879:70:0;27536:325:1;107103:271:0;107256:32;107266:4;107272:2;107276:11;107256:9;:32::i;:::-;107307:52;107330:4;107336:2;107340:11;107353:5;107307:22;:52::i;:::-;107299:67;;;;-1:-1:-1;;;107299:67:0;;27738:2:1;107299:67:0;;;27720:21:1;27777:1;27757:18;;;27750:29;-1:-1:-1;;;27795:18:1;;;27788:32;27837:18;;107299:67:0;27536:325:1;90118:622:0;90442:19;;90414:25;;;;90398:13;;90414:47;;;:::i;:::-;90398:63;;90472:30;90483:11;90496:5;90472:10;:30::i;:::-;90520:40;;;;:27;:40;;;;;90513:47;;;90690:11;90682:19;;:5;:19;:::i;:::-;90662:16;;:39;;;;;;;:::i;:::-;;;;-1:-1:-1;90714:18:0;;-1:-1:-1;90720:11:0;90714:5;:18::i;100155:678::-;100304:24;100330:16;72459:5;100394:57;100411:5;100418:15;100394:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;100394:57:0;-1:-1:-1;;;;;100394:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100435:15;100394:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;100394:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;:16;:57::i;:::-;100371:20;;:80;;;-1:-1:-1;;;100371:20:0;;-1:-1:-1;;;;;100371:20:0;:80;:::i;:::-;-1:-1:-1;;;;;100370:96:0;;;;;:::i;:::-;100359:107;-1:-1:-1;72459:5:0;100584:22;100359:107;72459:5;100584:22;:::i;:::-;100565:42;;:15;:42;:::i;:::-;100564:58;;;;:::i;:::-;100546:76;;:15;:76;:::i;:::-;100535:87;;100649:13;100637:8;:25;100633:193;;-1:-1:-1;100698:1:0;;-1:-1:-1;100725:13:0;100633:193;;;100790:24;100806:8;100790:13;:24;:::i;:::-;100771:43;;100155:678;;;;;;:::o;73276:1434::-;73417:6;73445;73468:1;73452:6;:13;:17;;;;:::i;:::-;73445:25;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;73440:30:0;:1;-1:-1:-1;;;;;73440:30:0;;73436:1267;;73494:6;73517:1;73501:6;:13;:17;;;;:::i;:::-;73494:25;;;;;;;;:::i;:::-;;;;;;;73487:32;;;;73436:1267;73546:6;73553:1;73546:9;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;73541:14:0;:1;-1:-1:-1;;;;;73541:14:0;;73537:1166;;73579:6;73586:1;73579:9;;;;;;;;:::i;73537:1166::-;73621:13;73649;73681:1;73665:6;:13;:17;;;;:::i;:::-;73649:33;;73697:11;73723:248;73746:1;73730:13;73738:5;73730;:13;:::i;:::-;:17;73723:248;;;73800:1;73783:13;73791:5;73783;:13;:::i;:::-;73782:19;;;;:::i;:::-;73774:27;;:5;:27;:::i;:::-;73768:33;;73839:1;-1:-1:-1;;;;;73824:16:0;:6;73831:3;73824:11;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;73824:16:0;;73820:136;;73873:3;73865:11;;73723:248;;73820:136;73933:3;73925:11;;73723:248;;;74005:6;74012:5;74005:13;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;73989:29:0;:6;73996:5;73989:13;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;73989:29:0;;73985:707;;;74446:6;74453:5;74446:13;;;;;;;;:::i;:::-;;;;;;;74430:6;74437:5;74430:13;;;;;;;;:::i;:::-;;;;;;;:29;;;;:::i;:::-;74390:6;74397:5;74390:13;;;;;;;;:::i;:::-;;;;;;;74386:1;:17;;;;:::i;:::-;74368:6;74375:5;74368:13;;;;;;;;:::i;:::-;;;;;;;74352:6;74359:5;74352:13;;;;;;;;:::i;:::-;;;;;;;:29;;;;:::i;:::-;74351:53;;;;:::i;:::-;74350:110;;;;:::i;:::-;74313:6;74320:5;74313:13;;;;;;;;:::i;:::-;;;;;;;:147;;;;:::i;:::-;74285:175;;;;;;;73985:707;74662:6;74669:5;74662:13;;;;;;;;:::i;:::-;;;;;;;74646:6;74653:5;74646:13;;;;;;;;:::i;:::-;;;;;;;:29;;;;:::i;:::-;74606:6;74613:5;74606:13;;;;;;;;:::i;:::-;;;;;;;74602:1;:17;;;;:::i;:::-;74584:6;74591:5;74584:13;;;;;;;;:::i;:::-;;;;;;;74568:6;74575:5;74568:13;;;;;;;;:::i;:::-;;;;;;;:29;;;;:::i;:::-;74567:53;;;;:::i;:::-;74566:110;;;;:::i;:::-;74529:6;74536:5;74529:13;;;;;;;;:::i;:::-;;;;;;;:147;;;;:::i;93949:1160::-;94068:21;94091:30;94272:17;94344:4;94321:9;:19;;;94293:9;:25;;;:47;;;;:::i;:::-;94292:56;;;;:::i;:::-;94272:76;;94599:9;:16;;;94571:9;:25;;;:44;;;;:::i;:::-;94558:9;:57;94554:548;;94633:1;94617:17;;94554:548;;;94941:9;94922;:16;;;94894:9;:25;;;:44;;;;:::i;:::-;:56;;;;:::i;:::-;95028:17;;95000:25;;;;94878:72;;-1:-1:-1;95000:45:0;;-1:-1:-1;;;;;95028:17:0;;;;95000:45;:::i;:::-;94969:27;72459:5;94969:13;:27;:::i;:::-;:76;94965:125;;95089:1;95064:26;;94965:125;94128:981;93949:1160;;;;;:::o;96936:520::-;97015:12;97177:25;72459:5;97239:13;;;;;;;;;-1:-1:-1;;;;;97239:13:0;-1:-1:-1;;;;;97206:46:0;:13;;;;;;;;;-1:-1:-1;;;;;97206:13:0;-1:-1:-1;;;;;97206:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:46;;;;:::i;:::-;97205:62;;;;:::i;:::-;97177:90;;97303:17;97282:18;:38;97278:170;;;97387:17;97351:32;72459:5;97351:18;:32;:::i;:::-;97350:54;;;;:::i;:::-;97335:70;;97278:170;;;72459:5;97421:27;;97278:170;97029:427;96936:520;;;:::o;37009:716::-;37433:23;37459:69;37487:4;37459:69;;;;;;;;;;;;;;;;;37467:5;-1:-1:-1;;;;;37459:27:0;;;:69;;;;;:::i;:::-;37543:17;;37433:95;;-1:-1:-1;37543:21:0;37539:179;;37640:10;37629:30;;;;;;;;;;;;:::i;:::-;37621:85;;;;-1:-1:-1;;;37621:85:0;;33473:2:1;37621:85:0;;;33455:21:1;33512:2;33492:18;;;33485:30;33551:34;33531:18;;;33524:62;-1:-1:-1;;;33602:18:1;;;33595:40;33652:19;;37621:85:0;33271:406:1;39386:451:0;39461:13;39487:19;39519:10;39523:6;39519:1;:10;:::i;:::-;:14;;39532:1;39519:14;:::i;:::-;-1:-1:-1;;;;;39509:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;39509:25:0;;39487:47;;-1:-1:-1;;;39545:6:0;39552:1;39545:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;39545:15:0;;;;;;;;;-1:-1:-1;;;39571:6:0;39578:1;39571:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;39571:15:0;;;;;;;;-1:-1:-1;39602:9:0;39614:10;39618:6;39614:1;:10;:::i;:::-;:14;;39627:1;39614:14;:::i;:::-;39602:26;;39597:135;39634:1;39630;:5;39597:135;;;-1:-1:-1;;;39682:5:0;39690:3;39682:11;39669:25;;;;;;;:::i;:::-;;;;39657:6;39664:1;39657:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;39657:37:0;;;;;;;;-1:-1:-1;39719:1:0;39709:11;;;;;39637:3;;;:::i;:::-;;;39597:135;;;-1:-1:-1;39750:10:0;;39742:55;;;;-1:-1:-1;;;39742:55:0;;24643:2:1;39742:55:0;;;24625:21:1;;;24662:18;;;24655:30;24721:34;24701:18;;;24694:62;24773:18;;39742:55:0;24441:356:1;101112:202:0;101172:7;101192:19;101232:12;;101214:15;:30;:63;;101265:12;;101214:63;;;101247:15;101192:85;101112:202;-1:-1:-1;;101112:202:0:o;2726:65::-;1592:13;;;;;;;;:30;;-1:-1:-1;1610:12:0;;;;1609:13;1592:30;1584:89;;;;-1:-1:-1;;;1584:89:0;;;;;;;:::i;:::-;1709:13;;;;;;;1708:14;1733:101;;;;1768:13;:20;;-1:-1:-1;;1803:19:0;;;;;1860:68;;;;1895:13;:21;;-1:-1:-1;;1895:21:0;;;1573:362;2726:65::o;4176:92::-;1592:13;;;;;;;;:30;;-1:-1:-1;1610:12:0;;;;1609:13;1592:30;1584:89;;;;-1:-1:-1;;;1584:89:0;;;;;;;:::i;:::-;1709:13;;;;;;;1708:14;1733:101;;;;1768:13;:20;;-1:-1:-1;;1803:19:0;;;;;1733:101;4245:7:::1;:15:::0;;-1:-1:-1;;4245:15:0::1;::::0;;1860:68;;;;1895:13;:21;;-1:-1:-1;;1895:21:0;;;1573:362;4176:92::o;110958:884::-;111117:4;-1:-1:-1;;;;;111138:13:0;;26793:20;26841:8;111134:701;;111174:85;;-1:-1:-1;;;111174:85:0;;-1:-1:-1;;;;;111174:47:0;;;;;:85;;111222:10;;111234:4;;111240:11;;111253:5;;111174:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;111174:85:0;;;;;;;;-1:-1:-1;;111174:85:0;;;;;;;;;;;;:::i;:::-;;;111170:610;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;111476:13:0;;111472:293;;111519:12;;-1:-1:-1;;;111519:12:0;;27738:2:1;111519:12:0;;;27720:21:1;27777:1;27757:18;;;27750:29;-1:-1:-1;;;27795:18:1;;;27788:32;27837:18;;111519:12:0;27536:325:1;111472:293:0;111715:6;111709:13;111700:6;111696:2;111692:15;111685:38;111170:610;-1:-1:-1;;;;;;111342:66:0;-1:-1:-1;;;111342:66:0;;-1:-1:-1;111335:73:0;;111134:701;-1:-1:-1;111819:4:0;110958:884;;;;;;:::o;109083:349::-;109139:13;109155:21;109164:11;109155:8;:21::i;:::-;109139:37;;109217:33;109234:1;109238:11;109217:8;:33::i;:::-;-1:-1:-1;;;;;109263:16:0;;;;;;:9;:16;;;;;:21;;109283:1;;109263:16;:21;;109283:1;;109263:21;:::i;:::-;;;;-1:-1:-1;;109302:20:0;;;;:7;:20;;;;;;;;109295:27;;-1:-1:-1;;;;;;109295:27:0;;;109340:13;:26;;;;;;109333:33;;;109295:27;109333:33;;;;;;;;;;;;;;;;109384:40;109310:11;;109302:20;-1:-1:-1;;;;;109384:40:0;;;;;109302:20;;109384:40;109128:304;109083:349;:::o;29276:229::-;29413:12;29445:52;29467:6;29475:4;29481:1;29484:12;29413;26793:20;;30683:60;;;;-1:-1:-1;;;30683:60:0;;32456:2:1;30683:60:0;;;32438:21:1;32495:2;32475:18;;;32468:30;32534:31;32514:18;;;32507:59;32583:18;;30683:60:0;32254:353:1;30683:60:0;30757:12;30771:23;30798:6;-1:-1:-1;;;;;30798:11:0;30817:5;30824:4;30798:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30756:73;;;;30847:51;30864:7;30873:10;30885:12;30847:16;:51::i;:::-;30840:58;30396:510;-1:-1:-1;;;;;;;30396:510:0:o;33082:712::-;33232:12;33261:7;33257:530;;;-1:-1:-1;33292:10:0;33285:17;;33257:530;33406:17;;:21;33402:374;;33604:10;33598:17;33665:15;33652:10;33648:2;33644:19;33637:44;33402:374;33747:12;33740:20;;-1:-1:-1;;;33740:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:406:1;78:5;-1:-1:-1;;;;;104:6:1;101:30;98:56;;;134:18;;:::i;:::-;172:57;217:2;196:15;;-1:-1:-1;;192:29:1;223:4;188:40;172:57;:::i;:::-;163:66;;252:6;245:5;238:21;292:3;283:6;278:3;274:16;271:25;268:45;;;309:1;306;299:12;268:45;358:6;353:3;346:4;339:5;335:16;322:43;412:1;405:4;396:6;389:5;385:18;381:29;374:40;14:406;;;;;:::o;425:134::-;493:20;;522:31;493:20;522:31;:::i;564:677::-;617:5;670:3;663:4;655:6;651:17;647:27;637:55;;688:1;685;678:12;637:55;724:6;711:20;750:4;774:60;790:43;830:2;790:43;:::i;:::-;774:60;:::i;:::-;856:3;880:2;875:3;868:15;908:2;903:3;899:12;892:19;;943:2;935:6;931:15;995:3;990:2;984;981:1;977:10;969:6;965:23;961:32;958:41;955:61;;;1012:1;1009;1002:12;955:61;1034:1;1044:168;1058:2;1055:1;1052:9;1044:168;;;1115:22;1133:3;1115:22;:::i;:::-;1103:35;;1158:12;;;;1190;;;;1076:1;1069:9;1044:168;;;-1:-1:-1;1230:5:1;;564:677;-1:-1:-1;;;;;;;564:677:1:o;1246:171::-;1313:20;;-1:-1:-1;;;;;1362:30:1;;1352:41;;1342:69;;1407:1;1404;1397:12;1422:247;1481:6;1534:2;1522:9;1513:7;1509:23;1505:32;1502:52;;;1550:1;1547;1540:12;1502:52;1589:9;1576:23;1608:31;1633:5;1608:31;:::i;1674:251::-;1744:6;1797:2;1785:9;1776:7;1772:23;1768:32;1765:52;;;1813:1;1810;1803:12;1765:52;1845:9;1839:16;1864:31;1889:5;1864:31;:::i;1930:388::-;1998:6;2006;2059:2;2047:9;2038:7;2034:23;2030:32;2027:52;;;2075:1;2072;2065:12;2027:52;2114:9;2101:23;2133:31;2158:5;2133:31;:::i;:::-;2183:5;-1:-1:-1;2240:2:1;2225:18;;2212:32;2253:33;2212:32;2253:33;:::i;:::-;2305:7;2295:17;;;1930:388;;;;;:::o;2323:456::-;2400:6;2408;2416;2469:2;2457:9;2448:7;2444:23;2440:32;2437:52;;;2485:1;2482;2475:12;2437:52;2524:9;2511:23;2543:31;2568:5;2543:31;:::i;:::-;2593:5;-1:-1:-1;2650:2:1;2635:18;;2622:32;2663:33;2622:32;2663:33;:::i;:::-;2323:456;;2715:7;;-1:-1:-1;;;2769:2:1;2754:18;;;;2741:32;;2323:456::o;2784:794::-;2879:6;2887;2895;2903;2956:3;2944:9;2935:7;2931:23;2927:33;2924:53;;;2973:1;2970;2963:12;2924:53;3012:9;2999:23;3031:31;3056:5;3031:31;:::i;:::-;3081:5;-1:-1:-1;3138:2:1;3123:18;;3110:32;3151:33;3110:32;3151:33;:::i;:::-;3203:7;-1:-1:-1;3257:2:1;3242:18;;3229:32;;-1:-1:-1;3312:2:1;3297:18;;3284:32;-1:-1:-1;;;;;3328:30:1;;3325:50;;;3371:1;3368;3361:12;3325:50;3394:22;;3447:4;3439:13;;3435:27;-1:-1:-1;3425:55:1;;3476:1;3473;3466:12;3425:55;3499:73;3564:7;3559:2;3546:16;3541:2;3537;3533:11;3499:73;:::i;:::-;3489:83;;;2784:794;;;;;;;:::o;3583:382::-;3648:6;3656;3709:2;3697:9;3688:7;3684:23;3680:32;3677:52;;;3725:1;3722;3715:12;3677:52;3764:9;3751:23;3783:31;3808:5;3783:31;:::i;:::-;3833:5;-1:-1:-1;3890:2:1;3875:18;;3862:32;3903:30;3862:32;3903:30;:::i;3970:315::-;4038:6;4046;4099:2;4087:9;4078:7;4074:23;4070:32;4067:52;;;4115:1;4112;4105:12;4067:52;4154:9;4141:23;4173:31;4198:5;4173:31;:::i;:::-;4223:5;4275:2;4260:18;;;;4247:32;;-1:-1:-1;;;3970:315:1:o;4290:521::-;4385:6;4393;4401;4409;4417;4470:3;4458:9;4449:7;4445:23;4441:33;4438:53;;;4487:1;4484;4477:12;4438:53;4526:9;4513:23;4545:31;4570:5;4545:31;:::i;:::-;4595:5;4647:2;4632:18;;4619:32;;-1:-1:-1;4698:2:1;4683:18;;4670:32;;4749:2;4734:18;;4721:32;;-1:-1:-1;4800:3:1;4785:19;4772:33;;-1:-1:-1;4290:521:1;-1:-1:-1;;;4290:521:1:o;4816:1238::-;4963:6;4971;4979;4987;5040:3;5028:9;5019:7;5015:23;5011:33;5008:53;;;5057:1;5054;5047:12;5008:53;5097:9;5084:23;-1:-1:-1;;;;;5122:6:1;5119:30;5116:50;;;5162:1;5159;5152:12;5116:50;5185:22;;5238:4;5230:13;;5226:27;-1:-1:-1;5216:55:1;;5267:1;5264;5257:12;5216:55;5303:2;5290:16;5325:4;5349:60;5365:43;5405:2;5365:43;:::i;5349:60::-;5431:3;5455:2;5450:3;5443:15;5483:2;5478:3;5474:12;5467:19;;5514:2;5510;5506:11;5562:7;5557:2;5551;5548:1;5544:10;5540:2;5536:19;5532:28;5529:41;5526:61;;;5583:1;5580;5573:12;5526:61;5605:1;5596:10;;5615:238;5629:2;5626:1;5623:9;5615:238;;;5700:3;5687:17;5717:31;5742:5;5717:31;:::i;:::-;5761:18;;5647:1;5640:9;;;;;5799:12;;;;5831;;5615:238;;;-1:-1:-1;5872:5:1;-1:-1:-1;5896:38:1;;-1:-1:-1;5915:18:1;;;5896:38;:::i;:::-;5886:48;;;;;5953:38;5987:2;5976:9;5972:18;5953:38;:::i;:::-;5943:48;;6010:38;6044:2;6033:9;6029:18;6010:38;:::i;:::-;6000:48;;4816:1238;;;;;;;:::o;6059:902::-;6143:6;6174:2;6217;6205:9;6196:7;6192:23;6188:32;6185:52;;;6233:1;6230;6223:12;6185:52;6273:9;6260:23;-1:-1:-1;;;;;6298:6:1;6295:30;6292:50;;;6338:1;6335;6328:12;6292:50;6361:22;;6414:4;6406:13;;6402:27;-1:-1:-1;6392:55:1;;6443:1;6440;6433:12;6392:55;6479:2;6466:16;6502:60;6518:43;6558:2;6518:43;:::i;6502:60::-;6584:3;6608:2;6603:3;6596:15;6636:2;6631:3;6627:12;6620:19;;6667:2;6663;6659:11;6715:7;6710:2;6704;6701:1;6697:10;6693:2;6689:19;6685:28;6682:41;6679:61;;;6736:1;6733;6726:12;6679:61;6758:1;6749:10;;6768:163;6782:2;6779:1;6776:9;6768:163;;;6839:17;;6827:30;;6800:1;6793:9;;;;;6877:12;;;;6909;;6768:163;;;-1:-1:-1;6950:5:1;6059:902;-1:-1:-1;;;;;;;6059:902:1:o;6966:591::-;7082:6;7090;7143:2;7131:9;7122:7;7118:23;7114:32;7111:52;;;7159:1;7156;7149:12;7111:52;7199:9;7186:23;-1:-1:-1;;;;;7269:2:1;7261:6;7258:14;7255:34;;;7285:1;7282;7275:12;7255:34;7308:60;7360:7;7351:6;7340:9;7336:22;7308:60;:::i;:::-;7298:70;;7421:2;7410:9;7406:18;7393:32;7377:48;;7450:2;7440:8;7437:16;7434:36;;;7466:1;7463;7456:12;7434:36;;7489:62;7543:7;7532:8;7521:9;7517:24;7489:62;:::i;:::-;7479:72;;;6966:591;;;;;:::o;7562:722::-;7685:6;7693;7701;7754:2;7742:9;7733:7;7729:23;7725:32;7722:52;;;7770:1;7767;7760:12;7722:52;7810:9;7797:23;-1:-1:-1;;;;;7880:2:1;7872:6;7869:14;7866:34;;;7896:1;7893;7886:12;7866:34;7919:60;7971:7;7962:6;7951:9;7947:22;7919:60;:::i;:::-;7909:70;;8032:2;8021:9;8017:18;8004:32;7988:48;;8061:2;8051:8;8048:16;8045:36;;;8077:1;8074;8067:12;8045:36;;8100:62;8154:7;8143:8;8132:9;8128:24;8100:62;:::i;:::-;8090:72;;;8212:2;8201:9;8197:18;8184:32;8225:29;8248:5;8225:29;:::i;:::-;8273:5;8263:15;;;7562:722;;;;;:::o;8289:245::-;8356:6;8409:2;8397:9;8388:7;8384:23;8380:32;8377:52;;;8425:1;8422;8415:12;8377:52;8457:9;8451:16;8476:28;8498:5;8476:28;:::i;8539:180::-;8598:6;8651:2;8639:9;8630:7;8626:23;8622:32;8619:52;;;8667:1;8664;8657:12;8619:52;-1:-1:-1;8690:23:1;;8539:180;-1:-1:-1;8539:180:1:o;8724:315::-;8792:6;8800;8853:2;8841:9;8832:7;8828:23;8824:32;8821:52;;;8869:1;8866;8859:12;8821:52;8905:9;8892:23;8882:33;;8965:2;8954:9;8950:18;8937:32;8978:31;9003:5;8978:31;:::i;9044:245::-;9102:6;9155:2;9143:9;9134:7;9130:23;9126:32;9123:52;;;9171:1;9168;9161:12;9123:52;9210:9;9197:23;9229:30;9253:5;9229:30;:::i;9294:249::-;9363:6;9416:2;9404:9;9395:7;9391:23;9387:32;9384:52;;;9432:1;9429;9422:12;9384:52;9464:9;9458:16;9483:30;9507:5;9483:30;:::i;10516:450::-;10585:6;10638:2;10626:9;10617:7;10613:23;10609:32;10606:52;;;10654:1;10651;10644:12;10606:52;10694:9;10681:23;-1:-1:-1;;;;;10719:6:1;10716:30;10713:50;;;10759:1;10756;10749:12;10713:50;10782:22;;10835:4;10827:13;;10823:27;-1:-1:-1;10813:55:1;;10864:1;10861;10854:12;10813:55;10887:73;10952:7;10947:2;10934:16;10929:2;10925;10921:11;10887:73;:::i;11156:184::-;11226:6;11279:2;11267:9;11258:7;11254:23;11250:32;11247:52;;;11295:1;11292;11285:12;11247:52;-1:-1:-1;11318:16:1;;11156:184;-1:-1:-1;11156:184:1:o;11665:383::-;11742:6;11750;11758;11811:2;11799:9;11790:7;11786:23;11782:32;11779:52;;;11827:1;11824;11817:12;11779:52;11863:9;11850:23;11840:33;;11923:2;11912:9;11908:18;11895:32;11936:31;11961:5;11936:31;:::i;12053:248::-;12121:6;12129;12182:2;12170:9;12161:7;12157:23;12153:32;12150:52;;;12198:1;12195;12188:12;12150:52;-1:-1:-1;;12221:23:1;;;12291:2;12276:18;;;12263:32;;-1:-1:-1;12053:248:1:o;12306:245::-;12385:6;12393;12446:2;12434:9;12425:7;12421:23;12417:32;12414:52;;;12462:1;12459;12452:12;12414:52;-1:-1:-1;;12485:16:1;;12541:2;12526:18;;;12520:25;12485:16;;12520:25;;-1:-1:-1;12306:245:1:o;12556:383::-;12633:6;12641;12649;12702:2;12690:9;12681:7;12677:23;12673:32;12670:52;;;12718:1;12715;12708:12;12670:52;12754:9;12741:23;12731:33;;12811:2;12800:9;12796:18;12783:32;12773:42;;12865:2;12854:9;12850:18;12837:32;12878:31;12903:5;12878:31;:::i;12944:184::-;13002:6;13055:2;13043:9;13034:7;13030:23;13026:32;13023:52;;;13071:1;13068;13061:12;13023:52;13094:28;13112:9;13094:28;:::i;13133:256::-;13199:6;13207;13260:2;13248:9;13239:7;13235:23;13231:32;13228:52;;;13276:1;13273;13266:12;13228:52;13299:28;13317:9;13299:28;:::i;:::-;13289:38;;13346:37;13379:2;13368:9;13364:18;13346:37;:::i;:::-;13336:47;;13133:256;;;;;:::o;13394:247::-;13462:6;13515:2;13503:9;13494:7;13490:23;13486:32;13483:52;;;13531:1;13528;13521:12;13483:52;13563:9;13557:16;13582:29;13605:5;13582:29;:::i;13778:459::-;13830:3;13868:5;13862:12;13895:6;13890:3;13883:19;13921:4;13950:2;13945:3;13941:12;13934:19;;13987:2;13980:5;13976:14;14008:1;14018:194;14032:6;14029:1;14026:13;14018:194;;;14097:13;;-1:-1:-1;;;;;14093:38:1;14081:51;;14152:12;;;;14187:15;;;;14054:1;14047:9;14018:194;;;-1:-1:-1;14228:3:1;;13778:459;-1:-1:-1;;;;;13778:459:1:o;14242:1706::-;14334:12;;37349:19;;;14302:3;37186:14;;;37401:4;37217:18;;;37392:14;;;14302:3;;14334:12;14302:3;14533:581;14573:6;14569:1;14556:11;14552:19;14549:31;14533:581;;;14682:13;;-1:-1:-1;;;;;14767:13:1;;;16468:43;;14809:2;14846:13;;;14842:22;;14875:4;14866:14;;16468:43;14904:3;14942:13;;;14938:22;;;14962:12;;;16468:43;15010:3;15006:14;;;;15031:2;15022:12;;16468:43;15055:12;;;;15102:1;15090:14;;;;14635:1;14618:19;14533:581;;;15137:13;;;15162:23;;;15159:195;;;-1:-1:-1;;;;;15226:31:1;;16468:43;;15292:4;15283:14;;;;15342:1;15325:19;15159:195;15382:6;15369:11;15366:23;15363:204;;;-1:-1:-1;;;;;15438:2:1;15434:15;;;15430:40;16468:43;;15505:4;15496:14;;;;15555:1;15538:19;15363:204;15595:6;15582:11;15579:23;15576:205;;;-1:-1:-1;;;;;15651:3:1;15647:16;;;15643:41;16468:43;;15719:4;15710:14;;;;15769:1;15752:19;15576:205;15809:6;15796:11;15793:23;15790:133;;;15861:3;15857:16;;;16468:43;;15908:4;15903:3;15899:14;15892:21;;15790:133;-1:-1:-1;15939:3:1;;14242:1706;-1:-1:-1;;;;14242:1706:1:o;15953:268::-;16005:3;16043:5;16037:12;16070:6;16065:3;16058:19;16086:63;16142:6;16135:4;16130:3;16126:14;16119:4;16112:5;16108:16;16086:63;:::i;:::-;16203:2;16182:15;-1:-1:-1;;16178:29:1;16169:39;;;;16210:4;16165:50;;15953:268;-1:-1:-1;;15953:268:1:o;16226:184::-;16267:3;16305:5;16299:12;16320:52;16365:6;16360:3;16353:4;16346:5;16342:16;16320:52;:::i;:::-;16388:16;;;;;16226:184;-1:-1:-1;;16226:184:1:o;16522:274::-;16651:3;16689:6;16683:13;16705:53;16751:6;16746:3;16739:4;16731:6;16727:17;16705:53;:::i;:::-;16774:16;;;;;16522:274;-1:-1:-1;;16522:274:1:o;16801:1183::-;16977:3;17006:1;17039:6;17033:13;17069:3;17091:1;17119:9;17115:2;17111:18;17101:28;;17179:2;17168:9;17164:18;17201;17191:61;;17245:4;17237:6;17233:17;17223:27;;17191:61;17271:2;17319;17311:6;17308:14;17288:18;17285:38;17282:165;;;-1:-1:-1;;;17346:33:1;;17402:4;17399:1;17392:15;17432:4;17353:3;17420:17;17282:165;17463:18;17490:104;;;;17608:1;17603:330;;;;17456:477;;17490:104;-1:-1:-1;;17523:24:1;;17511:37;;17568:16;;;;-1:-1:-1;17490:104:1;;17603:330;37193:1;37186:14;;;37230:4;37217:18;;17708:1;17722:165;17736:6;17733:1;17730:13;17722:165;;;17814:14;;17801:11;;;17794:35;17857:16;;;;17751:10;;17722:165;;;17726:3;;17916:6;17911:3;17907:16;17900:23;;17456:477;;;;;;;17949:29;17974:3;17966:6;17949:29;:::i;17989:786::-;18400:25;18395:3;18388:38;18370:3;18455:6;18449:13;18471:62;18526:6;18521:2;18516:3;18512:12;18505:4;18497:6;18493:17;18471:62;:::i;:::-;-1:-1:-1;;;18592:2:1;18552:16;;;18584:11;;;18577:40;18642:13;;18664:63;18642:13;18713:2;18705:11;;18698:4;18686:17;;18664:63;:::i;:::-;18747:17;18766:2;18743:26;;17989:786;-1:-1:-1;;;;17989:786:1:o;19414:522::-;19608:4;-1:-1:-1;;;;;19718:2:1;19710:6;19706:15;19695:9;19688:34;19770:2;19762:6;19758:15;19753:2;19742:9;19738:18;19731:43;;19810:6;19805:2;19794:9;19790:18;19783:34;19853:3;19848:2;19837:9;19833:18;19826:31;19874:56;19925:3;19914:9;19910:19;19902:6;19874:56;:::i;20243:1495::-;20613:3;20626:22;;;20697:13;;20598:19;;;20719:22;;;20565:4;;20795;;20772:3;20757:19;;;20822:15;;;20565:4;20865:169;20879:6;20876:1;20873:13;20865:169;;;20940:13;;20928:26;;20974:12;;;;21009:15;;;;20901:1;20894:9;20865:169;;;-1:-1:-1;;;21070:19:1;;;21050:18;;;21043:47;21140:13;;21162:21;;;21238:15;;;;21201:12;;;21273:1;21283:327;21299:8;21294:3;21291:17;21283:327;;;21364:15;;21410:9;;-1:-1:-1;;;;;21406:58:1;21392:73;;21507:11;;21501:18;21485:14;;;21478:42;21583:17;;;;21553:4;21542:16;;;;21327:1;21318:11;21283:327;;;-1:-1:-1;;;;;;;13712:54:1;;21683:4;21668:20;;13700:67;21627:5;-1:-1:-1;21641:48:1;;-1:-1:-1;;13646:127:1;21641:48;21725:6;21720:2;21709:9;21705:18;21698:34;20243:1495;;;;;;;:::o;21743:537::-;22020:2;22009:9;22002:21;21983:4;22046:55;22097:2;22086:9;22082:18;22074:6;22046:55;:::i;:::-;22149:9;22141:6;22137:22;22132:2;22121:9;22117:18;22110:50;22177:43;22213:6;22205;22177:43;:::i;:::-;22169:51;;;22268:4;22260:6;22256:17;22251:2;22240:9;22236:18;22229:45;21743:537;;;;;;:::o;22285:469::-;22532:2;22521:9;22514:21;22495:4;22558:63;22617:2;22606:9;22602:18;22594:6;22558:63;:::i;:::-;22669:9;22661:6;22657:22;22652:2;22641:9;22637:18;22630:50;22697:51;22741:6;22733;22697:51;:::i;23877:230::-;24026:2;24015:9;24008:21;23989:4;24046:55;24097:2;24086:9;24082:18;24074:6;24046:55;:::i;27866:340::-;28068:2;28050:21;;;28107:2;28087:18;;;28080:30;-1:-1:-1;;;28141:2:1;28126:18;;28119:46;28197:2;28182:18;;27866:340::o;29201:410::-;29403:2;29385:21;;;29442:2;29422:18;;;29415:30;29481:34;29476:2;29461:18;;29454:62;-1:-1:-1;;;29547:2:1;29532:18;;29525:44;29601:3;29586:19;;29201:410::o;31925:324::-;32127:2;32109:21;;;32166:1;32146:18;;;32139:29;-1:-1:-1;;;32199:2:1;32184:18;;32177:31;32240:2;32225:18;;31925:324::o;34670:325::-;34872:2;34854:21;;;34911:1;34891:18;;;34884:29;-1:-1:-1;;;34944:2:1;34929:18;;34922:32;34986:2;34971:18;;34670:325::o;36642:275::-;36713:2;36707:9;36778:2;36759:13;;-1:-1:-1;;36755:27:1;36743:40;;-1:-1:-1;;;;;36798:34:1;;36834:22;;;36795:62;36792:88;;;36860:18;;:::i;:::-;36896:2;36889:22;36642:275;;-1:-1:-1;36642:275:1:o;36922:183::-;36982:4;-1:-1:-1;;;;;37007:6:1;37004:30;37001:56;;;37037:18;;:::i;:::-;-1:-1:-1;37082:1:1;37078:14;37094:4;37074:25;;36922:183::o;37417:128::-;37457:3;37488:1;37484:6;37481:1;37478:13;37475:39;;;37494:18;;:::i;:::-;-1:-1:-1;37530:9:1;;37417:128::o;37550:236::-;37589:3;-1:-1:-1;;;;;37662:2:1;37659:1;37655:10;37692:2;37689:1;37685:10;37723:3;37719:2;37715:12;37710:3;37707:21;37704:47;;;37731:18;;:::i;:::-;37767:13;;37550:236;-1:-1:-1;;;;37550:236:1:o;37791:120::-;37831:1;37857;37847:35;;37862:18;;:::i;:::-;-1:-1:-1;37896:9:1;;37791:120::o;37916:199::-;37955:1;-1:-1:-1;;;;;38026:2:1;38023:1;38019:10;38048:3;38038:37;;38055:18;;:::i;:::-;38093:10;;38089:20;;;;;37916:199;-1:-1:-1;;37916:199:1:o;38120:422::-;38209:1;38252:5;38209:1;38266:270;38287:7;38277:8;38274:21;38266:270;;;38346:4;38342:1;38338:6;38334:17;38328:4;38325:27;38322:53;;;38355:18;;:::i;:::-;38405:7;38395:8;38391:22;38388:55;;;38425:16;;;;38388:55;38504:22;;;;38464:15;;;;38266:270;;38547:140;38605:5;38634:47;38675:4;38665:8;38661:19;38655:4;38741:5;38771:8;38761:80;;-1:-1:-1;38812:1:1;38826:5;;38761:80;38860:4;38850:76;;-1:-1:-1;38897:1:1;38911:5;;38850:76;38942:4;38960:1;38955:59;;;;39028:1;39023:130;;;;38935:218;;38955:59;38985:1;38976:10;;38999:5;;;39023:130;39060:3;39050:8;39047:17;39044:43;;;39067:18;;:::i;:::-;-1:-1:-1;;39123:1:1;39109:16;;39138:5;;38935:218;;39237:2;39227:8;39224:16;39218:3;39212:4;39209:13;39205:36;39199:2;39189:8;39186:16;39181:2;39175:4;39172:12;39168:35;39165:77;39162:159;;;-1:-1:-1;39274:19:1;;;39306:5;;39162:159;39353:34;39378:8;39372:4;39353:34;:::i;:::-;39423:6;39419:1;39415:6;39411:19;39402:7;39399:32;39396:58;;;39434:18;;:::i;:::-;39472:20;;38692:806;-1:-1:-1;;;38692:806:1:o;39503:168::-;39543:7;39609:1;39605;39601:6;39597:14;39594:1;39591:21;39586:1;39579:9;39572:17;39568:45;39565:71;;;39616:18;;:::i;:::-;-1:-1:-1;39656:9:1;;39503:168::o;39676:270::-;39715:7;-1:-1:-1;;;;;39792:2:1;39789:1;39785:10;39822:2;39819:1;39815:10;39878:3;39874:2;39870:12;39865:3;39862:21;39855:3;39848:11;39841:19;39837:47;39834:73;;;39887:18;;:::i;:::-;39927:13;;39676:270;-1:-1:-1;;;;39676:270:1:o;39951:125::-;39991:4;40019:1;40016;40013:8;40010:34;;;40024:18;;:::i;:::-;-1:-1:-1;40061:9:1;;39951:125::o;40081:229::-;40120:4;-1:-1:-1;;;;;40217:10:1;;;;40187;;40239:12;;;40236:38;;;40254:18;;:::i;:::-;40291:13;;40081:229;-1:-1:-1;;;40081:229:1:o;40315:258::-;40387:1;40397:113;40411:6;40408:1;40405:13;40397:113;;;40487:11;;;40481:18;40468:11;;;40461:39;40433:2;40426:10;40397:113;;;40528:6;40525:1;40522:13;40519:48;;;-1:-1:-1;;40563:1:1;40545:16;;40538:27;40315:258::o;40578:136::-;40617:3;40645:5;40635:39;;40654:18;;:::i;:::-;-1:-1:-1;;;40690:18:1;;40578:136::o;40719:380::-;40798:1;40794:12;;;;40841;;;40862:61;;40916:4;40908:6;40904:17;40894:27;;40862:61;40969:2;40961:6;40958:14;40938:18;40935:38;40932:161;;;41015:10;41010:3;41006:20;41003:1;40996:31;41050:4;41047:1;41040:15;41078:4;41075:1;41068:15;41104:135;41143:3;-1:-1:-1;;41164:17:1;;41161:43;;;41184:18;;:::i;:::-;-1:-1:-1;41231:1:1;41220:13;;41104:135::o;41244:112::-;41276:1;41302;41292:35;;41307:18;;:::i;:::-;-1:-1:-1;41341:9:1;;41244:112::o;41361:127::-;41422:10;41417:3;41413:20;41410:1;41403:31;41453:4;41450:1;41443:15;41477:4;41474:1;41467:15;41493:127;41554:10;41549:3;41545:20;41542:1;41535:31;41585:4;41582:1;41575:15;41609:4;41606:1;41599:15;41625:127;41686:10;41681:3;41677:20;41674:1;41667:31;41717:4;41714:1;41707:15;41741:4;41738:1;41731:15;41757:127;41818:10;41813:3;41809:20;41806:1;41799:31;41849:4;41846:1;41839:15;41873:4;41870:1;41863:15;41889:154;-1:-1:-1;;;;;41968:5:1;41964:54;41957:5;41954:65;41944:93;;42033:1;42030;42023:12;42048:118;42134:5;42127:13;42120:21;42113:5;42110:32;42100:60;;42156:1;42153;42146:12;42171:131;-1:-1:-1;;;;;;42245:32:1;;42235:43;;42225:71;;42292:1;42289;42282:12;42307:114;42391:4;42384:5;42380:16;42373:5;42370:27;42360:55;;42411:1;42408;42401:12

Swarm Source

ipfs://45840058006f230868797238b1a0691e6a0b163718211cd780d1fcfd01a5532c
Loading...
Loading
Loading...
Loading
[ 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.