{"file_path":"PoolManager.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0 ^0.8.13 ^0.8.20;\r\n\r\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP.\r\n */\r\ninterface IERC20 {\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n\r\n    /**\r\n     * @dev Returns the value of tokens in existence.\r\n     */\r\n    function collateral() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the value of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address to, uint256 value) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\r\n     * caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 value) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\r\n     * allowance mechanism. `value` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\r\n}\r\n\r\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\r\n\r\n/**\r\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\r\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\r\n *\r\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\r\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\r\n * need to send a transaction, and thus is not required to hold Ether at all.\r\n *\r\n * ==== Security Considerations\r\n *\r\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\r\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\r\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\r\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\r\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\r\n * generally recommended is:\r\n *\r\n * ```solidity\r\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\r\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\r\n *     doThing(..., value);\r\n * }\r\n *\r\n * function doThing(..., uint256 value) public {\r\n *     token.safeTransferFrom(msg.sender, address(this), value);\r\n *     ...\r\n * }\r\n * ```\r\n *\r\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\r\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\r\n * {SafeERC20-safeTransferFrom}).\r\n *\r\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\r\n * contracts should have entry points that don't rely on permit.\r\n */\r\ninterface IERC20Permit {\r\n    /**\r\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\r\n     * given ``owner``'s signed approval.\r\n     *\r\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\r\n     * ordering also apply here.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `deadline` must be a timestamp in the future.\r\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\r\n     * over the EIP712-formatted function arguments.\r\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\r\n     *\r\n     * For more information on the signature format, see the\r\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\r\n     * section].\r\n     *\r\n     * CAUTION: See Security Considerations above.\r\n     */\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) external;\r\n\r\n    /**\r\n     * @dev Returns the current nonce for `owner`. This value must be\r\n     * included whenever a signature is generated for {permit}.\r\n     *\r\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\r\n     * prevents a signature from being used multiple times.\r\n     */\r\n    function nonces(address owner) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\r\n     */\r\n    // solhint-disable-next-line func-name-mixedcase\r\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\r\n}\r\n\r\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\r\n\r\n/**\r\n * @dev Collection of functions related to the address type\r\n */\r\nlibrary Address {\r\n    /**\r\n     * @dev The ETH balance of the account is not enough to perform the operation.\r\n     */\r\n    error AddressInsufficientBalance(address account);\r\n\r\n    /**\r\n     * @dev There's no code at `target` (it is not a contract).\r\n     */\r\n    error AddressEmptyCode(address target);\r\n\r\n    /**\r\n     * @dev A call to an address target failed. The target may have reverted.\r\n     */\r\n    error FailedInnerCall();\r\n\r\n    /**\r\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\r\n     * `recipient`, forwarding all available gas and reverting on errors.\r\n     *\r\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\r\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\r\n     * imposed by `transfer`, making them unable to receive funds via\r\n     * `transfer`. {sendValue} removes this limitation.\r\n     *\r\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\r\n     *\r\n     * IMPORTANT: because control is transferred to `recipient`, care must be\r\n     * taken to not create reentrancy vulnerabilities. Consider using\r\n     * {ReentrancyGuard} or the\r\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\r\n     */\r\n    function sendValue(address payable recipient, uint256 amount) internal {\r\n        if (address(this).balance < amount) {\r\n            revert AddressInsufficientBalance(address(this));\r\n        }\r\n\r\n        (bool success, ) = recipient.call{value: amount}(\"\");\r\n        if (!success) {\r\n            revert FailedInnerCall();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Performs a Solidity function call using a low level `call`. A\r\n     * plain `call` is an unsafe replacement for a function call: use this\r\n     * function instead.\r\n     *\r\n     * If `target` reverts with a revert reason or custom error, it is bubbled\r\n     * up by this function (like regular Solidity function calls). However, if\r\n     * the call reverted with no returned reason, this function reverts with a\r\n     * {FailedInnerCall} error.\r\n     *\r\n     * Returns the raw returned data. To convert to the expected return value,\r\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `target` must be a contract.\r\n     * - calling `target` with `data` must not revert.\r\n     */\r\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but also transferring `value` wei to `target`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the calling contract must have an ETH balance of at least `value`.\r\n     * - the called Solidity function must be `payable`.\r\n     */\r\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\r\n        if (address(this).balance < value) {\r\n            revert AddressInsufficientBalance(address(this));\r\n        }\r\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\r\n        return verifyCallResultFromTarget(target, success, returndata);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a static call.\r\n     */\r\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.staticcall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.delegatecall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata);\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\r\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\r\n     * unsuccessful call.\r\n     */\r\n    function verifyCallResultFromTarget(\r\n        address target,\r\n        bool success,\r\n        bytes memory returndata\r\n    ) internal view returns (bytes memory) {\r\n        if (!success) {\r\n            _revert(returndata);\r\n        } else {\r\n            // only check if target is a contract if the call was successful and the return data is empty\r\n            // otherwise we already know that it was a contract\r\n            if (returndata.length == 0 && target.code.length == 0) {\r\n                revert AddressEmptyCode(target);\r\n            }\r\n            return returndata;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\r\n     * revert reason or with a default {FailedInnerCall} error.\r\n     */\r\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\r\n        if (!success) {\r\n            _revert(returndata);\r\n        } else {\r\n            return returndata;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\r\n     */\r\n    function _revert(bytes memory returndata) private pure {\r\n        // Look for revert reason and bubble it up if present\r\n        if (returndata.length > 0) {\r\n            // The easiest way to bubble the revert reason is using memory via assembly\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                let returndata_size := mload(returndata)\r\n                revert(add(32, returndata), returndata_size)\r\n            }\r\n        } else {\r\n            revert FailedInnerCall();\r\n        }\r\n    }\r\n}\r\n\r\n// lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\r\n\r\n/**\r\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\r\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\r\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\r\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\r\n *\r\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\r\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\r\n * case an upgrade adds a module that needs to be initialized.\r\n *\r\n * For example:\r\n *\r\n * [.hljs-theme-light.nopadding]\r\n * ```solidity\r\n * contract MyToken is ERC20Upgradeable {\r\n *     function initialize() initializer public {\r\n *         __ERC20_init(\"MyToken\", \"MTK\");\r\n *     }\r\n * }\r\n *\r\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\r\n *     function initializeV2() reinitializer(2) public {\r\n *         __ERC20Permit_init(\"MyToken\");\r\n *     }\r\n * }\r\n * ```\r\n *\r\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\r\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\r\n *\r\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\r\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\r\n *\r\n * [CAUTION]\r\n * ====\r\n * Avoid leaving a contract uninitialized.\r\n *\r\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\r\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\r\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\r\n *\r\n * [.hljs-theme-light.nopadding]\r\n * ```\r\n * /// @custom:oz-upgrades-unsafe-allow constructor\r\n * constructor() {\r\n *     _disableInitializers();\r\n * }\r\n * ```\r\n * ====\r\n */\r\nabstract contract Initializable {\r\n    /**\r\n     * @dev Storage of the initializable contract.\r\n     *\r\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\r\n     * when using with upgradeable contracts.\r\n     *\r\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\r\n     */\r\n    struct InitializableStorage {\r\n        /**\r\n         * @dev Indicates that the contract has been initialized.\r\n         */\r\n        uint64 _initialized;\r\n        /**\r\n         * @dev Indicates that the contract is in the process of being initialized.\r\n         */\r\n        bool _initializing;\r\n    }\r\n\r\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\r\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\r\n\r\n    /**\r\n     * @dev The contract is already initialized.\r\n     */\r\n    error InvalidInitialization();\r\n\r\n    /**\r\n     * @dev The contract is not initializing.\r\n     */\r\n    error NotInitializing();\r\n\r\n    /**\r\n     * @dev Triggered when the contract has been initialized or reinitialized.\r\n     */\r\n    event Initialized(uint64 version);\r\n\r\n    /**\r\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\r\n     * `onlyInitializing` functions can be used to initialize parent contracts.\r\n     *\r\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\r\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\r\n     * production.\r\n     *\r\n     * Emits an {Initialized} event.\r\n     */\r\n    modifier initializer() {\r\n        // solhint-disable-next-line var-name-mixedcase\r\n        InitializableStorage storage $ = _getInitializableStorage();\r\n\r\n        // Cache values to avoid duplicated sloads\r\n        bool isTopLevelCall = !$._initializing;\r\n        uint64 initialized = $._initialized;\r\n\r\n        // Allowed calls:\r\n        // - initialSetup: the contract is not in the initializing state and no previous version was\r\n        //                 initialized\r\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\r\n        //                 current contract is just being deployed\r\n        bool initialSetup = initialized == 0 && isTopLevelCall;\r\n        bool construction = initialized == 1 && address(this).code.length == 0;\r\n\r\n        if (!initialSetup && !construction) {\r\n            revert InvalidInitialization();\r\n        }\r\n        $._initialized = 1;\r\n        if (isTopLevelCall) {\r\n            $._initializing = true;\r\n        }\r\n        _;\r\n        if (isTopLevelCall) {\r\n            $._initializing = false;\r\n            emit Initialized(1);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\r\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\r\n     * used to initialize parent contracts.\r\n     *\r\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\r\n     * are added through upgrades and that require initialization.\r\n     *\r\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\r\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\r\n     *\r\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\r\n     * a contract, executing them in the right order is up to the developer or operator.\r\n     *\r\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\r\n     *\r\n     * Emits an {Initialized} event.\r\n     */\r\n    modifier reinitializer(uint64 version) {\r\n        // solhint-disable-next-line var-name-mixedcase\r\n        InitializableStorage storage $ = _getInitializableStorage();\r\n\r\n        if ($._initializing || $._initialized >= version) {\r\n            revert InvalidInitialization();\r\n        }\r\n        $._initialized = version;\r\n        $._initializing = true;\r\n        _;\r\n        $._initializing = false;\r\n        emit Initialized(version);\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\r\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\r\n     */\r\n    modifier onlyInitializing() {\r\n        _checkInitializing();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\r\n     */\r\n    function _checkInitializing() internal view virtual {\r\n        if (!_isInitializing()) {\r\n            revert NotInitializing();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\r\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\r\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\r\n     * through proxies.\r\n     *\r\n     * Emits an {Initialized} event the first time it is successfully executed.\r\n     */\r\n    function _disableInitializers() internal virtual {\r\n        // solhint-disable-next-line var-name-mixedcase\r\n        InitializableStorage storage $ = _getInitializableStorage();\r\n\r\n        if ($._initializing) {\r\n            revert InvalidInitialization();\r\n        }\r\n        if ($._initialized != type(uint64).max) {\r\n            $._initialized = type(uint64).max;\r\n            emit Initialized(type(uint64).max);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\r\n     */\r\n    function _getInitializedVersion() internal view returns (uint64) {\r\n        return _getInitializableStorage()._initialized;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\r\n     */\r\n    function _isInitializing() internal view returns (bool) {\r\n        return _getInitializableStorage()._initializing;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns a pointer to the storage namespace.\r\n     */\r\n    // solhint-disable-next-line var-name-mixedcase\r\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\r\n        assembly {\r\n            $.slot := INITIALIZABLE_STORAGE\r\n        }\r\n    }\r\n}\r\n\r\n// src/interfaces/IFBTC1.sol\r\n\r\ninterface IFireBridge {\r\n    struct Request {\r\n        uint256 amount;\r\n        uint256 fee;\r\n    }\r\n\r\n    function addBurnRequest(\r\n        uint256 _amount\r\n    ) external returns (bytes32 _hash, Request memory _r);\r\n\r\n    function addMintRequest(\r\n        uint256 _amount,\r\n        bytes32 _depositTxid,\r\n        uint256 _outputIndex\r\n    ) external returns (bytes32 _hash, Request memory _r);\r\n}\r\n\r\ninterface IFBTC1 {\r\n    function mintLockedFbtcRequest(\r\n        uint256 _amount\r\n    ) external returns (uint256 realAmount);\r\n\r\n    function redeemFbtcRequest(\r\n        uint256 _amount,\r\n        bytes32 _depositTxid,\r\n        uint256 _outputIndex\r\n    ) external returns (bytes32 _hash, IFireBridge.Request memory _r);\r\n\r\n    function confirmRedeemFbtc(uint256 _amount) external;\r\n\r\n    function burn(uint256 _amount) external;\r\n}\r\n\r\n// src/interfaces/IOracle.sol\r\n\r\n// Chainlink Contracts v0.8\r\n\r\ninterface AggregatorV3Interface {\r\n    function decimals() external view returns (uint8);\r\n\r\n    function description() external view returns (string memory);\r\n\r\n    function version() external view returns (uint256);\r\n\r\n    function getRoundData(\r\n        uint80 _roundId\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            uint80 roundId,\r\n            int256 answer,\r\n            uint256 startedAt,\r\n            uint256 updatedAt,\r\n            uint80 answeredInRound\r\n        );\r\n\r\n    function latestRoundData()\r\n        external\r\n        view\r\n        returns (\r\n            uint80 roundId,\r\n            int256 answer,\r\n            uint256 startedAt,\r\n            uint256 updatedAt,\r\n            uint80 answeredInRound\r\n        );\r\n}\r\n\r\n/**\r\n * @title IFBTCOracle\r\n * @notice Interface for the FBTC Oracle contract\r\n */\r\ninterface IFBTCOracle {\r\n    // Define an event that is emitted when the asset source is set\r\n    event AssetSourceSet(address indexed assetSource);\r\n\r\n    // Define an event that is emitted when the expired time is set\r\n    event ExpiredTimeSet(uint256 expiredTime);\r\n\r\n    /**\r\n     * @notice Sets the asset's price source\r\n     * @dev This function should be callable only by the contract owner\r\n     * @param source The address of the source of the asset\r\n     */\r\n    function setAssetSource(AggregatorV3Interface source) external;\r\n\r\n    /**\r\n     * @notice Gets the price of the asset\r\n     * @dev This is a view function that does not alter the blockchain state\r\n     * @return The price of the asset\r\n     */\r\n    function getAssetPrice() external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Gets the number of decimals used by the price source\r\n     * @dev This is a view function that does not alter the blockchain state\r\n     * @return The number of decimals\r\n     */\r\n    function decimals() external view returns (uint8);\r\n}\r\n\r\n// src/protocol/library/math/WadRayMath.sol\r\n\r\n/**\r\n * @title WadRayMath library\r\n * @author Aave\r\n * @notice Provides functions to perform calculations with Wad and Ray units\r\n * @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers\r\n * with 27 digits of precision)\r\n * @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.\r\n */\r\nlibrary WadRayMath {\r\n  // HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly\r\n  uint256 internal constant WAD = 1e18;\r\n  uint256 internal constant HALF_WAD = 0.5e18;\r\n\r\n  uint256 internal constant RAY = 1e27;\r\n  uint256 internal constant HALF_RAY = 0.5e27;\r\n\r\n  uint256 internal constant WAD_RAY_RATIO = 1e9;\r\n\r\n  /**\r\n   * @dev Multiplies two wad, rounding half up to the nearest wad\r\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\r\n   * @param a Wad\r\n   * @param b Wad\r\n   * @return c = a*b, in wad\r\n   */\r\n  function wadMul(uint256 a, uint256 b) internal pure returns (uint256 c) {\r\n    // to avoid overflow, a <= (type(uint256).max - HALF_WAD) / b\r\n    assembly {\r\n      if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_WAD), b))))) {\r\n        revert(0, 0)\r\n      }\r\n\r\n      c := div(add(mul(a, b), HALF_WAD), WAD)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * @dev Divides two wad, rounding half up to the nearest wad\r\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\r\n   * @param a Wad\r\n   * @param b Wad\r\n   * @return c = a/b, in wad\r\n   */\r\n  function wadDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {\r\n    // to avoid overflow, a <= (type(uint256).max - halfB) / WAD\r\n    assembly {\r\n      if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), WAD))))) {\r\n        revert(0, 0)\r\n      }\r\n\r\n      c := div(add(mul(a, WAD), div(b, 2)), b)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * @notice Multiplies two ray, rounding half up to the nearest ray\r\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\r\n   * @param a Ray\r\n   * @param b Ray\r\n   * @return c = a raymul b\r\n   */\r\n  function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) {\r\n    // to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b\r\n    assembly {\r\n      if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) {\r\n        revert(0, 0)\r\n      }\r\n\r\n      c := div(add(mul(a, b), HALF_RAY), RAY)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * @notice Divides two ray, rounding half up to the nearest ray\r\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\r\n   * @param a Ray\r\n   * @param b Ray\r\n   * @return c = a raydiv b\r\n   */\r\n  function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {\r\n    // to avoid overflow, a <= (type(uint256).max - halfB) / RAY\r\n    assembly {\r\n      if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) {\r\n        revert(0, 0)\r\n      }\r\n\r\n      c := div(add(mul(a, RAY), div(b, 2)), b)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * @dev Casts ray down to wad\r\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\r\n   * @param a Ray\r\n   * @return b = a converted to wad, rounded half up to the nearest wad\r\n   */\r\n  function rayToWad(uint256 a) internal pure returns (uint256 b) {\r\n    assembly {\r\n      b := div(a, WAD_RAY_RATIO)\r\n      let remainder := mod(a, WAD_RAY_RATIO)\r\n      if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) {\r\n        b := add(b, 1)\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * @dev Converts wad up to ray\r\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\r\n   * @param a Wad\r\n   * @return b = a converted in ray\r\n   */\r\n  function wadToRay(uint256 a) internal pure returns (uint256 b) {\r\n    // to avoid overflow, b/WAD_RAY_RATIO == a\r\n    assembly {\r\n      b := mul(a, WAD_RAY_RATIO)\r\n\r\n      if iszero(eq(div(b, WAD_RAY_RATIO), a)) {\r\n        revert(0, 0)\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\r\n\r\n/**\r\n * @dev Interface for the optional metadata functions from the ERC20 standard.\r\n */\r\ninterface IERC20Metadata is IERC20 {\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token.\r\n     */\r\n    function symbol() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the decimals places of the token.\r\n     */\r\n    function decimals() external view returns (uint8);\r\n}\r\n\r\n// lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\r\n\r\n/**\r\n * @dev Provides information about the current execution context, including the\r\n * sender of the transaction and its data. While these are generally available\r\n * via msg.sender and msg.data, they should not be accessed in such a direct\r\n * manner, since when dealing with meta-transactions the account sending and\r\n * paying for execution may not be the actual sender (as far as an application\r\n * is concerned).\r\n *\r\n * This contract is only required for intermediate, library-like contracts.\r\n */\r\nabstract contract ContextUpgradeable is Initializable {\r\n    function __Context_init() internal onlyInitializing {\r\n    }\r\n\r\n    function __Context_init_unchained() internal onlyInitializing {\r\n    }\r\n    function _msgSender() internal view virtual returns (address) {\r\n        return msg.sender;\r\n    }\r\n\r\n    function _msgData() internal view virtual returns (bytes calldata) {\r\n        return msg.data;\r\n    }\r\n\r\n    function _contextSuffixLength() internal view virtual returns (uint256) {\r\n        return 0;\r\n    }\r\n}\r\n\r\n// src/protocol/library/math/MathUtils.sol\r\n\r\n/**\r\n * @title MathUtils library\r\n * @author Aave\r\n * @notice Provides functions to perform linear and compounded interest calculations\r\n */\r\nlibrary MathUtils {\r\n    using WadRayMath for uint256;\r\n\r\n    /// @dev Ignoring leap years\r\n    uint256 internal constant SECONDS_PER_YEAR = 365 days;\r\n\r\n    /**\r\n     * @dev Function to calculate the interest accumulated using a linear interest rate formula\r\n     * @param rate The interest rate, in ray\r\n     * @param lastUpdateTimestamp The timestamp of the last update of the interest\r\n     * @return The interest rate linearly accumulated during the timeDelta, in ray\r\n     */\r\n    function calculateLinearInterest(\r\n        uint256 rate,\r\n        uint40 lastUpdateTimestamp\r\n    ) internal view returns (uint256) {\r\n        //solium-disable-next-line\r\n        uint256 result = rate *\r\n            (block.timestamp - uint256(lastUpdateTimestamp));\r\n        unchecked {\r\n            result = result / SECONDS_PER_YEAR;\r\n        }\r\n\r\n        return WadRayMath.RAY + result;\r\n    }\r\n\r\n    /**\r\n     * @dev Function to calculate the interest using a compounded interest rate formula\r\n     * To avoid expensive exponentiation, the calculation is performed using a binomial approximation:\r\n     *\r\n     *  (1+x)^n = 1+n*x+[n/2*(n-1)]*x^2+[n/6*(n-1)*(n-2)*x^3...\r\n     *\r\n     * The approximation slightly underpays liquidity providers and undercharges borrowers, with the advantage of great\r\n     * gas cost reductions. The whitepaper contains reference to the approximation and a table showing the margin of\r\n     * error per different time periods\r\n     *\r\n     * @param rate The interest rate, in ray\r\n     * @param lastUpdateTimestamp The timestamp of the last update of the interest\r\n     * @return The interest rate compounded during the timeDelta, in ray\r\n     */\r\n    function calculateCompoundedInterest(\r\n        uint256 rate,\r\n        uint40 lastUpdateTimestamp,\r\n        uint256 currentTimestamp\r\n    ) internal pure returns (uint256) {\r\n        //solium-disable-next-line\r\n        uint256 exp = currentTimestamp - uint256(lastUpdateTimestamp);\r\n\r\n        if (exp == 0) {\r\n            return WadRayMath.RAY;\r\n        }\r\n\r\n        uint256 expMinusOne;\r\n        uint256 expMinusTwo;\r\n        uint256 basePowerTwo;\r\n        uint256 basePowerThree;\r\n        unchecked {\r\n            expMinusOne = exp - 1;\r\n\r\n            expMinusTwo = exp > 2 ? exp - 2 : 0;\r\n\r\n            basePowerTwo =\r\n                rate.rayMul(rate) /\r\n                (SECONDS_PER_YEAR * SECONDS_PER_YEAR);\r\n            basePowerThree = basePowerTwo.rayMul(rate) / SECONDS_PER_YEAR;\r\n        }\r\n\r\n        uint256 secondTerm = exp * expMinusOne * basePowerTwo;\r\n        unchecked {\r\n            secondTerm /= 2;\r\n        }\r\n        uint256 thirdTerm = exp * expMinusOne * expMinusTwo * basePowerThree;\r\n        unchecked {\r\n            thirdTerm /= 6;\r\n        }\r\n\r\n        return\r\n            WadRayMath.RAY +\r\n            (rate * exp) /\r\n            SECONDS_PER_YEAR +\r\n            secondTerm +\r\n            thirdTerm;\r\n    }\r\n\r\n    /**\r\n     * @dev Calculates the compounded interest between the timestamp of the last update and the current block timestamp\r\n     * @param rate The interest rate (in ray)\r\n     * @param lastUpdateTimestamp The timestamp from which the interest accumulation needs to be calculated\r\n     * @return The interest rate compounded between lastUpdateTimestamp and current block timestamp, in ray\r\n     */\r\n    function calculateCompoundedInterest(\r\n        uint256 rate,\r\n        uint40 lastUpdateTimestamp\r\n    ) internal view returns (uint256) {\r\n        return\r\n            calculateCompoundedInterest(\r\n                rate,\r\n                lastUpdateTimestamp,\r\n                block.timestamp\r\n            );\r\n    }\r\n}\r\n\r\n// lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\r\n\r\n/**\r\n * @dev Contract module which provides a basic access control mechanism, where\r\n * there is an account (an owner) that can be granted exclusive access to\r\n * specific functions.\r\n *\r\n * The initial owner is set to the address provided by the deployer. This can\r\n * later be changed with {transferOwnership}.\r\n *\r\n * This module is used through inheritance. It will make available the modifier\r\n * `onlyOwner`, which can be applied to your functions to restrict their use to\r\n * the owner.\r\n */\r\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\r\n    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\r\n    struct OwnableStorage {\r\n        address _owner;\r\n    }\r\n\r\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\r\n    bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\r\n\r\n    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\r\n        assembly {\r\n            $.slot := OwnableStorageLocation\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev The caller account is not authorized to perform an operation.\r\n     */\r\n    error OwnableUnauthorizedAccount(address account);\r\n\r\n    /**\r\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\r\n     */\r\n    error OwnableInvalidOwner(address owner);\r\n\r\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r\n\r\n    /**\r\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\r\n     */\r\n    function __Ownable_init(address initialOwner) internal onlyInitializing {\r\n        __Ownable_init_unchained(initialOwner);\r\n    }\r\n\r\n    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\r\n        if (initialOwner == address(0)) {\r\n            revert OwnableInvalidOwner(address(0));\r\n        }\r\n        _transferOwnership(initialOwner);\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if called by any account other than the owner.\r\n     */\r\n    modifier onlyOwner() {\r\n        _checkOwner();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the address of the current owner.\r\n     */\r\n    function owner() public view virtual returns (address) {\r\n        OwnableStorage storage $ = _getOwnableStorage();\r\n        return $._owner;\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if the sender is not the owner.\r\n     */\r\n    function _checkOwner() internal view virtual {\r\n        if (owner() != _msgSender()) {\r\n            revert OwnableUnauthorizedAccount(_msgSender());\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Leaves the contract without owner. It will not be possible to call\r\n     * `onlyOwner` functions. Can only be called by the current owner.\r\n     *\r\n     * NOTE: Renouncing ownership will leave the contract without an owner,\r\n     * thereby disabling any functionality that is only available to the owner.\r\n     */\r\n    function renounceOwnership() public virtual onlyOwner {\r\n        _transferOwnership(address(0));\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     * Can only be called by the current owner.\r\n     */\r\n    function transferOwnership(address newOwner) public virtual onlyOwner {\r\n        if (newOwner == address(0)) {\r\n            revert OwnableInvalidOwner(address(0));\r\n        }\r\n        _transferOwnership(newOwner);\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     * Internal function without access restriction.\r\n     */\r\n    function _transferOwnership(address newOwner) internal virtual {\r\n        OwnableStorage storage $ = _getOwnableStorage();\r\n        address oldOwner = $._owner;\r\n        $._owner = newOwner;\r\n        emit OwnershipTransferred(oldOwner, newOwner);\r\n    }\r\n}\r\n\r\n// lib/openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)\r\n\r\n/**\r\n * @dev Contract module which allows children to implement an emergency stop\r\n * mechanism that can be triggered by an authorized account.\r\n *\r\n * This module is used through inheritance. It will make available the\r\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\r\n * the functions of your contract. Note that they will not be pausable by\r\n * simply including this module, only once the modifiers are put in place.\r\n */\r\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\r\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\r\n    struct PausableStorage {\r\n        bool _paused;\r\n    }\r\n\r\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\r\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\r\n\r\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\r\n        assembly {\r\n            $.slot := PausableStorageLocation\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Emitted when the pause is triggered by `account`.\r\n     */\r\n    event Paused(address account);\r\n\r\n    /**\r\n     * @dev Emitted when the pause is lifted by `account`.\r\n     */\r\n    event Unpaused(address account);\r\n\r\n    /**\r\n     * @dev The operation failed because the contract is paused.\r\n     */\r\n    error EnforcedPause();\r\n\r\n    /**\r\n     * @dev The operation failed because the contract is not paused.\r\n     */\r\n    error ExpectedPause();\r\n\r\n    /**\r\n     * @dev Initializes the contract in unpaused state.\r\n     */\r\n    function __Pausable_init() internal onlyInitializing {\r\n        __Pausable_init_unchained();\r\n    }\r\n\r\n    function __Pausable_init_unchained() internal onlyInitializing {\r\n        PausableStorage storage $ = _getPausableStorage();\r\n        $._paused = false;\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to make a function callable only when the contract is not paused.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must not be paused.\r\n     */\r\n    modifier whenNotPaused() {\r\n        _requireNotPaused();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to make a function callable only when the contract is paused.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must be paused.\r\n     */\r\n    modifier whenPaused() {\r\n        _requirePaused();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if the contract is paused, and false otherwise.\r\n     */\r\n    function paused() public view virtual returns (bool) {\r\n        PausableStorage storage $ = _getPausableStorage();\r\n        return $._paused;\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if the contract is paused.\r\n     */\r\n    function _requireNotPaused() internal view virtual {\r\n        if (paused()) {\r\n            revert EnforcedPause();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if the contract is not paused.\r\n     */\r\n    function _requirePaused() internal view virtual {\r\n        if (!paused()) {\r\n            revert ExpectedPause();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Triggers stopped state.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must not be paused.\r\n     */\r\n    function _pause() internal virtual whenNotPaused {\r\n        PausableStorage storage $ = _getPausableStorage();\r\n        $._paused = true;\r\n        emit Paused(_msgSender());\r\n    }\r\n\r\n    /**\r\n     * @dev Returns to normal state.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must be paused.\r\n     */\r\n    function _unpause() internal virtual whenPaused {\r\n        PausableStorage storage $ = _getPausableStorage();\r\n        $._paused = false;\r\n        emit Unpaused(_msgSender());\r\n    }\r\n}\r\n\r\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\r\n\r\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\r\n\r\n/**\r\n * @title SafeERC20\r\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\r\n * contract returns false). Tokens that return no value (and instead revert or\r\n * throw on failure) are also supported, non-reverting calls are assumed to be\r\n * successful.\r\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\r\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\r\n */\r\nlibrary SafeERC20 {\r\n    using Address for address;\r\n\r\n    /**\r\n     * @dev An operation with an ERC20 token failed.\r\n     */\r\n    error SafeERC20FailedOperation(address token);\r\n\r\n    /**\r\n     * @dev Indicates a failed `decreaseAllowance` request.\r\n     */\r\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\r\n\r\n    /**\r\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\r\n    }\r\n\r\n    /**\r\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\r\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\r\n    }\r\n\r\n    /**\r\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        uint256 oldAllowance = token.allowance(address(this), spender);\r\n        forceApprove(token, spender, oldAllowance + value);\r\n    }\r\n\r\n    /**\r\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\r\n     * value, non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\r\n        unchecked {\r\n            uint256 currentAllowance = token.allowance(address(this), spender);\r\n            if (currentAllowance < requestedDecrease) {\r\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\r\n            }\r\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\r\n     * to be set to zero before setting it to a non-zero value, such as USDT.\r\n     */\r\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\r\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\r\n\r\n        if (!_callOptionalReturnBool(token, approvalCall)) {\r\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\r\n            _callOptionalReturn(token, approvalCall);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     */\r\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\r\n        // the target address contains contract code and also asserts for success in the low-level call.\r\n\r\n        bytes memory returndata = address(token).functionCall(data);\r\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\r\n            revert SafeERC20FailedOperation(address(token));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     *\r\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\r\n     */\r\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\r\n        // and not revert is the subcall reverts.\r\n\r\n        (bool success, bytes memory returndata) = address(token).call(data);\r\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\r\n    }\r\n}\r\n\r\n// src/protocol/library/type/DataTypes.sol\r\n\r\n/**\r\n * @title DataTypes\r\n * @dev Library containing various data structures used in the pool management system.\r\n */\r\nlibrary DataTypes {\r\n    /**\r\n     * @dev Structure to hold the configuration of the Pool Manager.\r\n     * @param DEFAULT_LIQUIDATION_THRESHOLD Default maximum withdrawal rate (e.g., 50%).\r\n     * @param DEFAULT_POOL_INTEREST_RATE Default interest rate (e.g., 5%).\r\n     * @param DEFAULT_LTV Default loan-to-value ratio (e.g., 5%).\r\n     * @param DEFAULT_PROTOCOL_INTEREST_RATE Protocol fee ratio.\r\n     * @param USDT ERC20 USDT contract.\r\n     * @param FBTC0 ERC20 FBTC0 contract.\r\n     * @param FBTC1 Interface for the FBTC1 contract.\r\n     * @param FBTCOracle Interface for the FBTC Oracle contract.\r\n     * @param AvalonUSDTVault Address of the Avalon USDT vault.\r\n     * @param AntaphaUSDTVault Address of the Antapha USDT vault.\r\n     */\r\n    struct PoolManagerConfig {\r\n        uint256 DEFAULT_LTV;\r\n        uint256 DEFAULT_LIQUIDATION_THRESHOLD;\r\n        uint256 DEFAULT_POOL_INTEREST_RATE;\r\n        uint256 DEFAULT_PROTOCOL_INTEREST_RATE;\r\n        IERC20 USDT;\r\n        IERC20 FBTC0;\r\n        IFBTC1 FBTC1;\r\n        IFBTCOracle FBTCOracle;\r\n        address AvalonUSDTVault;\r\n        address AntaphaUSDTVault;\r\n    }\r\n\r\n    /**\r\n     * @dev Structure to hold the reserve information of the Pool Manager.\r\n     * @param userAmount Total amount deposited by the user.\r\n     * @param collateral Total collateral provided by the user.\r\n     * @param debt Total debt owed by the user.\r\n     * @param claimableUSDT Amount of USDT that can be claimed by the user.\r\n     * @param claimableBTC Amount of BTC that can be claimed by the user.\r\n     */\r\n    struct PoolManagerReserveInformation {\r\n        uint256 userAmount;\r\n        uint256 collateral;\r\n        uint256 debt;\r\n        uint256 claimableUSDT;\r\n        uint256 claimableBTC;\r\n    }\r\n\r\n    /**\r\n     * @dev Structure to hold the configuration of a user's pool.\r\n     * @param init Indicates whether the user's pool is initialized.\r\n     * @param poolInterestRate Interest rate for the user's pool.\r\n     * @param protocolInterestRate Protocol interest rate for the user's pool.\r\n     * @param loanToValue Loan-to-value ratio for the user's pool.\r\n     * @param liquidationThreshold Maximum withdrawal rate for the user's pool.\r\n     */\r\n    struct UserPoolConfig {\r\n        bool init;\r\n        uint256 poolInterestRate;\r\n        uint256 protocolInterestRate;\r\n        uint256 loanToValue;\r\n        uint256 liquidationThreshold;\r\n    }\r\n\r\n    /**\r\n     * @dev Structure to hold the reserve information of a user's pool.\r\n     * @param timeStampIndex Timestamp when the user last borrowed.\r\n     * @param collateral Total supply in the user's pool.\r\n     * @param debt Total amount borrowed from the user's pool.\r\n     * @param debtToProtocol Debt owed to the protocol.\r\n     * @param claimableUSDT Amount currently available for borrowing.\r\n     * @param claimableBTC Amount currently available for withdrawal.\r\n     */\r\n    struct UserPoolReserveInformation {\r\n        uint40 timeStampIndex;\r\n        uint256 collateral;\r\n        uint256 debt;\r\n        uint256 debtToProtocol;\r\n        uint256 claimableUSDT;\r\n        uint256 claimableBTC;\r\n    }\r\n}\r\n\r\n// src/interfaces/IPoolManager.sol\r\n\r\n/**\r\n * @title IPoolManager\r\n * @dev Interface for the PoolManager contract, defining events and function signatures.\r\n */\r\ninterface IPoolManager {\r\n    /**\r\n     * @dev Emitted when a new pool is created for a user.\r\n     * @param user The address of the user for whom the pool was created.\r\n     * @param userPoolConfig The configuration of the newly created user pool.\r\n     */\r\n    event PoolCreated(\r\n        address indexed user,\r\n        DataTypes.UserPoolConfig userPoolConfig\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user supplies assets to their pool.\r\n     * @param user The address of the user who supplied assets.\r\n     * @param amount The amount of assets supplied.\r\n     * @param userPoolReserveInformation The updated reserve information after the supply.\r\n     */\r\n    event Supply(\r\n        address indexed user,\r\n        uint256 amount,\r\n        DataTypes.UserPoolReserveInformation userPoolReserveInformation\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user borrows assets from their pool.\r\n     * @param user The address of the user who borrowed assets.\r\n     * @param amount The amount of assets borrowed.\r\n     * @param userPoolReserveInformation The updated reserve information after the borrow.\r\n     */\r\n    event Borrow(\r\n        address indexed user,\r\n        uint256 amount,\r\n        DataTypes.UserPoolReserveInformation userPoolReserveInformation\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user claims USDT from their pool.\r\n     * @param user The address of the user who claimed USDT.\r\n     * @param amount The amount of USDT claimed.\r\n     * @param userPoolReserveInformation The updated reserve information after the claim.\r\n     */\r\n    event ClaimUSDT(\r\n        address indexed user,\r\n        uint256 amount,\r\n        DataTypes.UserPoolReserveInformation userPoolReserveInformation\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user repays their debt.\r\n     * @param user The address of the user who repaid.\r\n     * @param amount The amount repaid.\r\n     * @param userPoolReserveInformation The updated reserve information after the repayment.\r\n     */\r\n    event Repay(\r\n        address indexed user,\r\n        uint256 amount,\r\n        DataTypes.UserPoolReserveInformation userPoolReserveInformation\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user's position is liquidated.\r\n     * @param user The address of the user whose position was liquidated.\r\n     * @param collateral The amount of collateral liquidated.\r\n     * @param debt The amount of debt covered by the liquidation.\r\n     */\r\n    event Liquidation(address indexed user, uint256 collateral, uint256 debt);\r\n\r\n    /**\r\n     * @dev Emitted when a user withdraws assets from their pool.\r\n     * @param user The address of the user who withdrew assets.\r\n     * @param amount The amount of assets withdrawn.\r\n     * @param userPoolReserveInformation The updated reserve information after the withdrawal.\r\n     */\r\n    event Withdraw(\r\n        address indexed user,\r\n        uint256 amount,\r\n        DataTypes.UserPoolReserveInformation userPoolReserveInformation\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a request to mint FBTC0 is made.\r\n     * @param amount The amount of FBTC0 requested to be minted.\r\n     * @param depositTxid The transaction ID of the deposit.\r\n     * @param outputIndex The output index in the transaction.\r\n     */\r\n    event RequestMintFBTC0(\r\n        uint256 amount,\r\n        bytes32 depositTxid,\r\n        uint256 outputIndex\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user claims BTC from their pool.\r\n     * @param user The address of the user who claimed BTC.\r\n     * @param amount The amount of BTC claimed.\r\n     * @param userPoolReserveInformation The updated reserve information after the claim.\r\n     */\r\n    event ClaimBTC(\r\n        address indexed user,\r\n        uint256 amount,\r\n        DataTypes.UserPoolReserveInformation userPoolReserveInformation\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user's pool state is updated.\r\n     * @param user The address of the user whose pool state was updated.\r\n     * @param feeForPool The fee allocated to the pool.\r\n     * @param feeForProtocol The fee allocated to the protocol.\r\n     */\r\n    event UpdateState(\r\n        address indexed user,\r\n        uint256 feeForPool,\r\n        uint256 feeForProtocol\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when a user's pool configuration is updated.\r\n     * @param user The address of the user whose pool configuration was updated.\r\n     * @param poolInterestRate The new pool interest rate.\r\n     * @param protocolInterestRate The new protocol interest rate.\r\n     * @param loanToValue The new loan-to-value ratio.\r\n     * @param liquidationThreshold The new liquidation threshold.\r\n     */\r\n    event UserPoolConfigUpdated(\r\n        address indexed user,\r\n        uint256 poolInterestRate,\r\n        uint256 protocolInterestRate,\r\n        uint256 loanToValue,\r\n        uint256 liquidationThreshold\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when protocol earnings are claimed.\r\n     * @param claimant The address of the account that claimed the earnings.\r\n     * @param amount The amount of earnings claimed.\r\n     */\r\n    event ProtocolEarningsClaimed(address indexed claimant, uint256 amount);\r\n\r\n    function createPool(address user) external;\r\n\r\n    function supply(uint256 amount) external;\r\n\r\n    function borrow(uint256 amount) external;\r\n\r\n    function repay(uint256 amount) external payable;\r\n\r\n    function withdraw(uint256 amount) external;\r\n\r\n    function liquidate(\r\n        address user,\r\n        uint256 collateralDecrease,\r\n        uint256 debtDecrease\r\n    ) external;\r\n\r\n    function claimUSDT(uint256 amount) external;\r\n\r\n    function claimBTC(uint256 amount) external;\r\n\r\n    function claimProtocolEarnings() external;\r\n\r\n    function requestMintFBTC0(\r\n        uint256 amount,\r\n        bytes32 depositTxid,\r\n        uint256 outputIndex\r\n    ) external;\r\n\r\n    function setUserPoolConfig(\r\n        address user,\r\n        uint256 poolInterestRate,\r\n        uint256 protocolInterestRate,\r\n        uint256 loanToValue,\r\n        uint256 liquidationThreshold\r\n    ) external;\r\n\r\n    function getUserPoolReserveInformation(\r\n        address user\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            DataTypes.UserPoolReserveInformation memory reserveAfterUpdateDebt\r\n        );\r\n\r\n    function getPoolManagerReserveInformation()\r\n        external\r\n        view\r\n        returns (\r\n            DataTypes.PoolManagerReserveInformation\r\n                memory poolManagerReserveInfor\r\n        );\r\n\r\n    function calculateAccumulatedDebt(\r\n        uint256 debt,\r\n        uint256 poolInterestRate,\r\n        uint256 protocolInterestRate,\r\n        uint40 timeStampIndex\r\n    ) external view returns (uint256 feeForPool, uint256 feeForProtocol);\r\n\r\n    function calculateMaxBorrowAmount(\r\n        uint256 loanToValue,\r\n        uint256 collateral,\r\n        uint256 debt,\r\n        uint256 FBTC0Price,\r\n        uint256 USDTDecimal,\r\n        uint256 FBTC0Decimal,\r\n        uint256 oracleDecimal\r\n    ) external view returns (uint256);\r\n\r\n    function calculateMaxWithdrawAmount(\r\n        uint256 liquidationThreshold,\r\n        uint256 collateral,\r\n        uint256 debt,\r\n        uint256 FBTC0Price,\r\n        uint256 USDTDecimal,\r\n        uint256 FBTC0Decimal,\r\n        uint256 oracleDecimal\r\n    ) external view returns (uint256);\r\n}\r\n\r\n// src/protocol/PoolManagerStorage.sol\r\n\r\n/**\r\n * @title PoolManagerStorage\r\n * @dev Storage contract for managing pool-related data and access control.\r\n */\r\ncontract PoolManagerStorage {\r\n    uint256 public constant DENOMINATOR = 10000;\r\n\r\n    address internal _emergencyController;\r\n\r\n    uint256 internal _protocolProfitUnclaimed;\r\n\r\n    uint256 internal _protocolProfitAccumulate;\r\n\r\n    address[] internal _userList;\r\n\r\n    DataTypes.PoolManagerConfig internal _poolManagerConfig;\r\n\r\n    DataTypes.PoolManagerReserveInformation\r\n        internal _poolManagerReserveInformation;\r\n\r\n    mapping(address => DataTypes.UserPoolConfig) internal _userPoolConfig;\r\n\r\n    mapping(address => DataTypes.UserPoolReserveInformation)\r\n        internal _userPoolReserveInformation;\r\n}\r\n\r\n// src/protocol/PoolManagerConfigurator.sol\r\n\r\n/**\r\n * @title PoolManagerConfigurator\r\n * @dev Contract for configuring and managing pool settings and user-specific configurations.\r\n * @notice This contract inherits from PoolManagerStorage, OwnableUpgradeable, and PausableUpgradeable.\r\n */\r\ncontract PoolManagerConfigurator is\r\n    PoolManagerStorage,\r\n    OwnableUpgradeable,\r\n    PausableUpgradeable\r\n{\r\n    /**\r\n     * @dev Modifier to check if the user's pool is initialized.\r\n     */\r\n    modifier onlyInitializedPool() {\r\n        require(_userPoolConfig[msg.sender].init, \"Pool not initialized\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to restrict access to the emergency controller.\r\n     */\r\n    modifier onlyEmergencyController() {\r\n        require(\r\n            msg.sender == _emergencyController,\r\n            \"caller is not emergencyController\"\r\n        );\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Initializes the contract with the specified owner.\r\n     * @param owner The address of the contract owner.\r\n     */\r\n    function initialize(address owner) public initializer {\r\n        __Ownable_init(owner);\r\n        __Pausable_init();\r\n    }\r\n\r\n    /**\r\n     * @dev Pauses the contract. Can only be called by the emergency controller.\r\n     */\r\n    function pause() external onlyEmergencyController {\r\n        _pause();\r\n    }\r\n\r\n    /**\r\n     * @dev Unpauses the contract. Can only be called by the emergency controller.\r\n     */\r\n    function unpause() external onlyEmergencyController {\r\n        _unpause();\r\n    }\r\n\r\n    /**\r\n     * @dev Sets the pool manager configuration. Can only be called by the owner.\r\n     * @param configInput The new configuration to set.\r\n     */\r\n    function setPoolManagerConfig(\r\n        DataTypes.PoolManagerConfig calldata configInput\r\n    ) external onlyOwner {\r\n        _poolManagerConfig = configInput;\r\n    }\r\n\r\n    /**\r\n     * @dev Sets the emergency controller address. Can only be called by the owner.\r\n     * @param emergencyController The address of the new emergency controller.\r\n     */\r\n    function setEmergencyController(\r\n        address emergencyController\r\n    ) external onlyOwner {\r\n        _emergencyController = emergencyController;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the pool manager configuration.\r\n     * @return The pool manager configuration as a `DataTypes.PoolManagerConfig` struct.\r\n     */\r\n    function getPoolManagerConfig()\r\n        external\r\n        view\r\n        returns (DataTypes.PoolManagerConfig memory)\r\n    {\r\n        return _poolManagerConfig;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the unclaimed protocol profit.\r\n     * @return The amount of unclaimed protocol profit as a uint256.\r\n     */\r\n    function getProtocolProfitUnclaimed() external view returns (uint256) {\r\n        return _protocolProfitUnclaimed;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the address of the emergency controller.\r\n     * @return The address of the emergency controller.\r\n     */\r\n    function getEmergencyController() external view returns (address) {\r\n        return _emergencyController;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the accumulated protocol profit.\r\n     * @return The total accumulated protocol profit as a uint256.\r\n     */\r\n    function getProtocolProfitAccumulate() external view returns (uint256) {\r\n        return _protocolProfitAccumulate;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the configuration of a user's pool.\r\n     * @param user The address of the user.\r\n     * @return The user's pool configuration as a `DataTypes.UserPoolConfig` struct.\r\n     */\r\n    function getUserPoolConfig(\r\n        address user\r\n    ) external view returns (DataTypes.UserPoolConfig memory) {\r\n        return _userPoolConfig[user];\r\n    }\r\n}\r\n\r\n// src/protocol/PoolManager.sol\r\n\r\n/**\r\n * @title PoolManager\r\n * @dev Manages liquidity pools and related operations.\r\n */\r\ncontract PoolManager is PoolManagerConfigurator, IPoolManager {\r\n    using WadRayMath for uint256;\r\n    using MathUtils for uint256;\r\n    using SafeERC20 for IERC20;\r\n\r\n    /**\r\n     * @dev Creates a new liquidity pool.\r\n     * Requirements:\r\n     * - The caller must have the POOL_ADMIN_ROLE.\r\n     * - The pool must not have been initialized.\r\n     */\r\n    function createPool(address user) external whenNotPaused onlyOwner {\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolConfig storage userPoolConfig = _userPoolConfig[user];\r\n        require(!userPoolConfig.init, \"Pool already initialized\");\r\n        userPoolConfig.init = true;\r\n        userPoolConfig.poolInterestRate = poolManagerConfig\r\n            .DEFAULT_POOL_INTEREST_RATE;\r\n        userPoolConfig.protocolInterestRate = poolManagerConfig\r\n            .DEFAULT_PROTOCOL_INTEREST_RATE;\r\n        userPoolConfig.liquidationThreshold = poolManagerConfig\r\n            .DEFAULT_LIQUIDATION_THRESHOLD;\r\n        userPoolConfig.loanToValue = poolManagerConfig.DEFAULT_LTV;\r\n        _poolManagerReserveInformation.userAmount += 1;\r\n        _userList.push(user);\r\n        emit PoolCreated(user, userPoolConfig);\r\n    }\r\n\r\n    /**\r\n     * @dev Supplies tokens to the pool.\r\n     * @param amount The amount of tokens to supply.\r\n     * Requirements:\r\n     * - The pool must have been initialized.\r\n     */\r\n    function supply(uint256 amount) external whenNotPaused onlyInitializedPool {\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                msg.sender\r\n            ];\r\n\r\n        poolManagerConfig.FBTC0.safeTransferFrom(\r\n            msg.sender,\r\n            address(this),\r\n            amount\r\n        );\r\n        poolManagerConfig.FBTC0.approve(\r\n            address(poolManagerConfig.FBTC1),\r\n            amount\r\n        );\r\n        poolManagerConfig.FBTC1.mintLockedFbtcRequest(amount);\r\n        userPoolReserveInformation.collateral += amount;\r\n        _poolManagerReserveInformation.collateral += amount;\r\n        emit Supply(msg.sender, amount, userPoolReserveInformation);\r\n    }\r\n\r\n    /**\r\n     * @dev Requests a loan from the pool.\r\n     * @param amount The amount of the loan requested.\r\n     * Requirements:\r\n     * - The pool must have been initialized.\r\n     * - The requested amount must not exceed the allowable loan-to-value ratio.\r\n     */\r\n    function borrow(uint256 amount) external whenNotPaused onlyInitializedPool {\r\n        updateState(msg.sender);\r\n\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolConfig storage userPoolConfig = _userPoolConfig[\r\n            msg.sender\r\n        ];\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                msg.sender\r\n            ];\r\n        require(\r\n            calculateMaxBorrowAmount(\r\n                userPoolConfig.loanToValue,\r\n                userPoolReserveInformation.collateral,\r\n                userPoolReserveInformation.debt,\r\n                poolManagerConfig.FBTCOracle.getAssetPrice(),\r\n                IERC20Metadata(address(poolManagerConfig.USDT)).decimals(),\r\n                IERC20Metadata(address(poolManagerConfig.FBTC0)).decimals(),\r\n                poolManagerConfig.FBTCOracle.decimals()\r\n            ) >= amount,\r\n            \"Requested amount exceeds allowable loanToValue\"\r\n        );\r\n\r\n        userPoolReserveInformation.debt += amount;\r\n        userPoolReserveInformation.claimableUSDT += amount;\r\n\r\n        _poolManagerReserveInformation.debt += amount;\r\n        _poolManagerReserveInformation.claimableUSDT += amount;\r\n\r\n        emit Borrow(msg.sender, amount, userPoolReserveInformation);\r\n    }\r\n\r\n    /**\r\n     * @dev Repays borrowed tokens.\r\n     * @param amount The amount of tokens to repay.\r\n     * Requirements:\r\n     * - The pool must have been initialized.\r\n     */\r\n    function repay(\r\n        uint256 amount\r\n    ) external payable whenNotPaused onlyInitializedPool {\r\n        updateState(msg.sender);\r\n\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                msg.sender\r\n            ];\r\n        DataTypes.PoolManagerReserveInformation\r\n            storage poolManagerReserveInformation = _poolManagerReserveInformation;\r\n\r\n        amount = amount > userPoolReserveInformation.debt\r\n            ? userPoolReserveInformation.debt\r\n            : amount;\r\n\r\n        poolManagerConfig.USDT.safeTransferFrom(\r\n            msg.sender,\r\n            address(this),\r\n            amount\r\n        );\r\n\r\n        uint256 repayAmountToProtocol = (amount *\r\n            userPoolReserveInformation.debtToProtocol) /\r\n            userPoolReserveInformation.debt;\r\n\r\n        uint256 repayAmountToPool = amount - repayAmountToProtocol;\r\n\r\n        poolManagerConfig.USDT.safeTransfer(\r\n            poolManagerConfig.AntaphaUSDTVault,\r\n            repayAmountToPool\r\n        );\r\n\r\n        userPoolReserveInformation.debt -= amount;\r\n        userPoolReserveInformation.debtToProtocol -= repayAmountToProtocol;\r\n        poolManagerReserveInformation.debt -= amount;\r\n\r\n        emit Repay(msg.sender, amount, userPoolReserveInformation);\r\n    }\r\n\r\n    /**\r\n     * @dev Requests a withdrawal from the pool.\r\n     * @param amount The amount to claimBTC.\r\n     * Requirements:\r\n     * - The pool must have been initialized.\r\n     * - The requested amount must not exceed the maximum allowable claimBTC amount.\r\n     */\r\n    function withdraw(\r\n        uint256 amount\r\n    ) external whenNotPaused onlyInitializedPool {\r\n        updateState(msg.sender);\r\n\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolConfig memory userPoolConfig = _userPoolConfig[\r\n            msg.sender\r\n        ];\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                msg.sender\r\n            ];\r\n        DataTypes.PoolManagerReserveInformation\r\n            storage poolManagerReserveInformation = _poolManagerReserveInformation;\r\n\r\n        require(\r\n            calculateMaxWithdrawAmount(\r\n                userPoolConfig.liquidationThreshold,\r\n                userPoolReserveInformation.collateral,\r\n                userPoolReserveInformation.debt,\r\n                poolManagerConfig.FBTCOracle.getAssetPrice(),\r\n                IERC20Metadata(address(poolManagerConfig.USDT)).decimals(),\r\n                IERC20Metadata(address(poolManagerConfig.FBTC0)).decimals(),\r\n                poolManagerConfig.FBTCOracle.decimals()\r\n            ) >= amount,\r\n            \"Requested amount exceeds allowable liquiditionThreshold\"\r\n        );\r\n\r\n        userPoolReserveInformation.collateral -= amount;\r\n        userPoolReserveInformation.claimableBTC += amount;\r\n\r\n        poolManagerReserveInformation.collateral -= amount;\r\n        poolManagerReserveInformation.claimableBTC += amount;\r\n        emit Withdraw(msg.sender, amount, userPoolReserveInformation);\r\n    }\r\n\r\n    /**\r\n     * @dev Liquidates a portion of the user's collateral and debt.\r\n     * @param user The address of the user being liquidated.\r\n     * @param collateralDecrease The amount of collateral to decrease.\r\n     * @param debtDecrease The amount of debt to decrease.\r\n     * Requirements:\r\n     * - The pool must have been initialized.\r\n     * - Only the owner can call this function.\r\n     */\r\n    function liquidate(\r\n        address user,\r\n        uint256 collateralDecrease,\r\n        uint256 debtDecrease\r\n    ) external whenNotPaused onlyOwner {\r\n        updateState(user);\r\n\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                user\r\n            ];\r\n        DataTypes.PoolManagerReserveInformation\r\n            storage poolManagerReserveInformation = _poolManagerReserveInformation;\r\n\r\n        userPoolReserveInformation.collateral -= collateralDecrease;\r\n        userPoolReserveInformation.debt -= debtDecrease;\r\n\r\n        poolManagerReserveInformation.collateral -= collateralDecrease;\r\n        poolManagerReserveInformation.debt -= debtDecrease;\r\n\r\n        poolManagerConfig.FBTC1.burn(collateralDecrease);\r\n        emit Liquidation(user, collateralDecrease, debtDecrease);\r\n    }\r\n\r\n    /**\r\n     * @dev Claims USDT from the pool.\r\n     * @param amount The amount of tokens to claimUSDT.\r\n     * Requirements:\r\n     * - The pool must have been initialized.\r\n     * - The amount to claimUSDT must not exceed the claimableUSDT amount.\r\n     */\r\n    function claimUSDT(\r\n        uint256 amount\r\n    ) external whenNotPaused onlyInitializedPool {\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                msg.sender\r\n            ];\r\n        DataTypes.PoolManagerReserveInformation\r\n            storage poolManagerReserveInformation = _poolManagerReserveInformation;\r\n\r\n        require(\r\n            userPoolReserveInformation.claimableUSDT >= amount,\r\n            \"Insufficient claimableUSDT amount\"\r\n        );\r\n        userPoolReserveInformation.claimableUSDT -= amount;\r\n        poolManagerReserveInformation.claimableUSDT -= amount;\r\n        poolManagerConfig.USDT.safeTransferFrom(\r\n            poolManagerConfig.AvalonUSDTVault,\r\n            msg.sender,\r\n            amount\r\n        );\r\n        emit ClaimUSDT(msg.sender, amount, userPoolReserveInformation);\r\n    }\r\n\r\n    /**\r\n     * @dev Claim FBTC0 from the pool.\r\n     * @param amount The amount of tokens to claimBTC.\r\n     * Requirements:\r\n     * - The pool must have been initialized.\r\n     */\r\n    function claimBTC(\r\n        uint256 amount\r\n    ) external whenNotPaused onlyInitializedPool {\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                msg.sender\r\n            ];\r\n        DataTypes.PoolManagerReserveInformation\r\n            storage poolManagerReserveInformation = _poolManagerReserveInformation;\r\n\r\n        require(\r\n            userPoolReserveInformation.claimableBTC >= amount,\r\n            \"Exceed claimBTC limit\"\r\n        );\r\n\r\n        userPoolReserveInformation.claimableBTC -= amount;\r\n        poolManagerReserveInformation.claimableBTC -= amount;\r\n        poolManagerConfig.FBTC1.confirmRedeemFbtc(amount);\r\n        poolManagerConfig.FBTC0.safeTransfer(msg.sender, amount);\r\n        emit ClaimBTC(msg.sender, amount, userPoolReserveInformation);\r\n    }\r\n\r\n    /**\r\n     * @dev Claims the accumulated protocol earnings.\r\n     * Requirements:\r\n     * - The caller must have the POOL_ADMIN_ROLE.\r\n     */\r\n    function claimProtocolEarnings() external whenNotPaused onlyOwner {\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n        uint256 claimAmount = poolManagerConfig.USDT.balanceOf(address(this));\r\n        poolManagerConfig.USDT.safeTransfer(msg.sender, claimAmount);\r\n        _protocolProfitUnclaimed -= claimAmount;\r\n        emit ProtocolEarningsClaimed(msg.sender, claimAmount);\r\n    }\r\n\r\n    /**\r\n     * @dev Requests the minting of FBTC0 tokens.\r\n     * @param amount The amount of FBTC0 tokens.\r\n     * @param depositTxid The transaction ID of the deposit.\r\n     * @param outputIndex The output index of the deposit transaction.\r\n     */\r\n    function requestMintFBTC0(\r\n        uint256 amount,\r\n        bytes32 depositTxid,\r\n        uint256 outputIndex\r\n    ) external whenNotPaused {\r\n        DataTypes.PoolManagerConfig\r\n            memory poolManagerConfig = _poolManagerConfig;\r\n\r\n        poolManagerConfig.FBTC1.redeemFbtcRequest(\r\n            amount,\r\n            depositTxid,\r\n            outputIndex\r\n        );\r\n\r\n        emit RequestMintFBTC0(amount, depositTxid, outputIndex);\r\n    }\r\n\r\n    /**\r\n     * @dev Updates the configuration of a specific user's pool.\r\n     * @param user The address of the user whose pool configuration is being updated.\r\n     * @param poolInterestRate The new pool interest rate to set.\r\n     * @param protocolInterestRate The new protocol interest rate to set.\r\n     * @param loanToValue The new loan-to-value ratio to set.\r\n     * @param liquidationThreshold The new liquidation threshold to set.\r\n     * @notice This function can only be called by the contract owner when the contract is not paused.\r\n     * @notice The pool must have been initialized for the specified user.\r\n     */\r\n    function setUserPoolConfig(\r\n        address user,\r\n        uint256 poolInterestRate,\r\n        uint256 protocolInterestRate,\r\n        uint256 loanToValue,\r\n        uint256 liquidationThreshold\r\n    ) external whenNotPaused onlyOwner {\r\n        DataTypes.UserPoolConfig storage userPoolConfig = _userPoolConfig[user];\r\n        require(userPoolConfig.init, \"Pool not initialized\");\r\n        updateState(user);\r\n        userPoolConfig.poolInterestRate = poolInterestRate;\r\n        userPoolConfig.protocolInterestRate = protocolInterestRate;\r\n        userPoolConfig.liquidationThreshold = liquidationThreshold;\r\n        userPoolConfig.loanToValue = loanToValue;\r\n        emit UserPoolConfigUpdated(\r\n            user,\r\n            poolInterestRate,\r\n            protocolInterestRate,\r\n            loanToValue,\r\n            liquidationThreshold\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @dev Updates the user's debt.\r\n     * @param user The address of the user.\r\n     */\r\n    function updateState(address user) internal {\r\n        // Load the user's pool configuration into memory\r\n        DataTypes.UserPoolConfig memory userPoolConfig = _userPoolConfig[user];\r\n        // Load the user's pool reserve information into storage\r\n        DataTypes.UserPoolReserveInformation\r\n            storage userPoolReserveInformation = _userPoolReserveInformation[\r\n                user\r\n            ];\r\n        DataTypes.PoolManagerReserveInformation\r\n            storage poolManagerReserveInformation = _poolManagerReserveInformation;\r\n\r\n        (uint256 feeForPool, uint256 feeForProtocol) = calculateAccumulatedDebt(\r\n            userPoolReserveInformation.debt,\r\n            userPoolConfig.poolInterestRate,\r\n            userPoolConfig.protocolInterestRate,\r\n            userPoolReserveInformation.timeStampIndex\r\n        );\r\n\r\n        userPoolReserveInformation.timeStampIndex = uint40(block.timestamp);\r\n        userPoolReserveInformation.debt += feeForPool + feeForProtocol;\r\n        userPoolReserveInformation.debtToProtocol += feeForProtocol;\r\n        poolManagerReserveInformation.debt += feeForPool + feeForProtocol;\r\n\r\n        _protocolProfitUnclaimed += feeForProtocol;\r\n        _protocolProfitAccumulate += feeForProtocol;\r\n        emit UpdateState(user, feeForPool, feeForProtocol);\r\n    }\r\n\r\n    //------------------------view functions--------------------------\r\n    /**\r\n     * @dev Gets the user's pool reserve information.\r\n     * @param user The address of the user.\r\n     * @return reserveAfterUpdateDebt The user's pool reserve information after updating the debt.\r\n     */\r\n    function getUserPoolReserveInformation(\r\n        address user\r\n    )\r\n        public\r\n        view\r\n        returns (\r\n            DataTypes.UserPoolReserveInformation memory reserveAfterUpdateDebt\r\n        )\r\n    {\r\n        DataTypes.UserPoolConfig memory userPoolConfig = _userPoolConfig[user];\r\n        DataTypes.UserPoolReserveInformation\r\n            memory userPoolReserveInformation = _userPoolReserveInformation[\r\n                user\r\n            ];\r\n        (uint256 feeForPool, uint256 feeForProtocol) = calculateAccumulatedDebt(\r\n            userPoolReserveInformation.debt,\r\n            userPoolConfig.poolInterestRate,\r\n            userPoolConfig.protocolInterestRate,\r\n            userPoolReserveInformation.timeStampIndex\r\n        );\r\n\r\n        reserveAfterUpdateDebt.timeStampIndex = userPoolReserveInformation\r\n            .timeStampIndex;\r\n        reserveAfterUpdateDebt.collateral = userPoolReserveInformation\r\n            .collateral;\r\n        reserveAfterUpdateDebt.claimableUSDT = userPoolReserveInformation\r\n            .claimableUSDT;\r\n        reserveAfterUpdateDebt.claimableBTC = userPoolReserveInformation\r\n            .claimableBTC;\r\n        reserveAfterUpdateDebt.debt =\r\n            userPoolReserveInformation.debt +\r\n            feeForPool +\r\n            feeForProtocol;\r\n        reserveAfterUpdateDebt.debtToProtocol =\r\n            userPoolReserveInformation.debtToProtocol +\r\n            feeForProtocol;\r\n    }\r\n\r\n    /**\r\n     * @dev Retrieves the current reserve information for the entire pool manager.\r\n     * @notice This function aggregates data from all user pools and the global pool manager state.\r\n     * @return poolManagerReserveInfor A struct containing the aggregated reserve information.\r\n     */\r\n    function getPoolManagerReserveInformation()\r\n        external\r\n        view\r\n        returns (\r\n            DataTypes.PoolManagerReserveInformation\r\n                memory poolManagerReserveInfor\r\n        )\r\n    {\r\n        uint256 length = _userList.length;\r\n        for (uint i = 0; i < _userList.length; i++) {\r\n            poolManagerReserveInfor.debt += getUserPoolReserveInformation(\r\n                _userList[i]\r\n            ).debt;\r\n        }\r\n        poolManagerReserveInfor.userAmount = _poolManagerReserveInformation\r\n            .userAmount;\r\n        poolManagerReserveInfor.collateral = _poolManagerReserveInformation\r\n            .collateral;\r\n        poolManagerReserveInfor.claimableUSDT = _poolManagerReserveInformation\r\n            .claimableUSDT;\r\n        poolManagerReserveInfor.claimableBTC = _poolManagerReserveInformation\r\n            .claimableBTC;\r\n    }\r\n\r\n    /**\r\n     * @dev Calculates the increasing interest for both the pool and the protocol.\r\n     * @param debt The total amount borrowed.\r\n     * @param poolInterestRate The interest rate for the pool.\r\n     * @param protocolInterestRate The interest rate for the protocol.\r\n     * @param timeStampIndex The timestamp when the borrowing occurred.\r\n     * @return feeForPool The calculated interest fee for the pool.\r\n     * @return feeForProtocol The calculated interest fee for the protocol.\r\n     */\r\n    function calculateAccumulatedDebt(\r\n        uint256 debt,\r\n        uint256 poolInterestRate,\r\n        uint256 protocolInterestRate,\r\n        uint40 timeStampIndex\r\n    ) public view returns (uint256 feeForPool, uint256 feeForProtocol) {\r\n        feeForPool =\r\n            debt.rayMul(\r\n                MathUtils.calculateCompoundedInterest(\r\n                    (poolInterestRate * WadRayMath.RAY) / DENOMINATOR,\r\n                    timeStampIndex\r\n                )\r\n            ) -\r\n            debt;\r\n\r\n        // Calculate the fee for the protocol based on the protocol fee interest rate and borrowed timestamp\r\n        feeForProtocol =\r\n            debt.rayMul(\r\n                MathUtils.calculateCompoundedInterest(\r\n                    (protocolInterestRate * WadRayMath.RAY) / DENOMINATOR,\r\n                    timeStampIndex\r\n                )\r\n            ) -\r\n            debt;\r\n    }\r\n\r\n    /**\r\n     * @dev Calculates the maximum borrowable amount.\r\n     * @param loanToValue The loan-to-value ratio.\r\n     * @param collateral The total supply in the pool.\r\n     * @param FBTC0Price The price of the FBTC0 token.\r\n     * @return The maximum amount that can be borrowed.\r\n     */\r\n    function calculateMaxBorrowAmount(\r\n        uint256 loanToValue,\r\n        uint256 collateral,\r\n        uint256 debt,\r\n        uint256 FBTC0Price,\r\n        uint256 USDTDecimal,\r\n        uint256 FBTC0Decimal,\r\n        uint256 oracleDecimal\r\n    ) public view returns (uint256) {\r\n        return\r\n            (((collateral * FBTC0Price * 10 ** USDTDecimal) /\r\n                (10 ** FBTC0Decimal * 10 ** oracleDecimal)) * loanToValue) /\r\n            DENOMINATOR -\r\n            debt;\r\n    }\r\n\r\n    /**\r\n     * @dev Calculates the maximum withdrawable amount.\r\n     * @param collateral The total supply in the pool.\r\n     * @param FBTC0Price The price of the FBTC0 token.\r\n     * @return The maximum amount that can be withdrawn.\r\n     */\r\n    function calculateMaxWithdrawAmount(\r\n        uint256 liquidationThreshold,\r\n        uint256 collateral,\r\n        uint256 debt,\r\n        uint256 FBTC0Price,\r\n        uint256 USDTDecimal,\r\n        uint256 FBTC0Decimal,\r\n        uint256 oracleDecimal\r\n    ) public view returns (uint256) {\r\n        if (debt == 0) {\r\n            return collateral;\r\n        } else {\r\n            return\r\n                collateral -\r\n                (debt *\r\n                    10 ** (oracleDecimal + FBTC0Decimal - USDTDecimal) *\r\n                    DENOMINATOR) /\r\n                (FBTC0Price * liquidationThreshold);\r\n        }\r\n    }\r\n}","deployed_bytecode":"0x6080604052600436106101d85760003560e01c80638456cb5911610102578063b8d10cbb11610095578063cc144e6b11610064578063cc144e6b146106ef578063f2fde38b14610704578063f4b861df14610724578063f733f0481461073957600080fd5b8063b8d10cbb14610671578063c4d66de814610691578063c5ebeaec146106b1578063c993cc9d146106d157600080fd5b8063a3d77310116100d1578063a3d7731014610598578063a82cc1a0146105b8578063aec0da92146105ed578063b0f9006a1461065157600080fd5b80638456cb59146104fc5780638da5cb5b146105115780639049f9d214610562578063918f86741461058257600080fd5b80634867f3cf1161017a578063690ecf7211610149578063690ecf72146103725780636aa76b09146103e55780636ca7dc89146104c7578063715018a6146104e757600080fd5b80634867f3cf146102ab57806352a028d2146102cb5780635c975abb14610322578063639571341461035257600080fd5b80632e1a7d4d116101b65780632e1a7d4d146102435780633540302314610263578063371fd8e6146102835780633f4ba83a1461029657600080fd5b80630593f63d146101dd5780630710285c146101ff5780631d709e4e1461021f575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612b11565b610759565b005b34801561020b57600080fd5b506101fd61021a366004612b55565b61082c565b34801561022b57600080fd5b506001545b6040519081526020015b60405180910390f35b34801561024f57600080fd5b506101fd61025e366004612b8a565b6109d8565b34801561026f57600080fd5b506101fd61027e366004612b8a565b610dc5565b6101fd610291366004612b8a565b610ff7565b3480156102a257600080fd5b506101fd6111c2565b3480156102b757600080fd5b506102306102c6366004612ba3565b6111f6565b3480156102d757600080fd5b506102e061126a565b60405161023a9190600060a082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015292915050565b34801561032e57600080fd5b506000805160206131ad8339815191525460ff16604051901515815260200161023a565b34801561035e57600080fd5b506101fd61036d366004612bef565b611328565b34801561037e57600080fd5b5061039261038d366004612c1b565b61145a565b60405161023a9190600060c08201905064ffffffffff83511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b3480156103f157600080fd5b506104ba6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810191909152506040805161014081018252600454815260055460208201526006549181019190915260075460608201526008546001600160a01b039081166080830152600954811660a0830152600a54811660c0830152600b54811660e0830152600c548116610100830152600d541661012082015290565b60405161023a9190612c38565b3480156104d357600080fd5b506101fd6104e2366004612c1b565b6115d6565b3480156104f357600080fd5b506101fd611600565b34801561050857600080fd5b506101fd611612565b34801561051d57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b03909116815260200161023a565b34801561056e57600080fd5b506101fd61057d366004612c1b565b611644565b34801561058e57600080fd5b5061023061271081565b3480156105a457600080fd5b506102306105b3366004612ba3565b61181c565b3480156105c457600080fd5b506105d86105d3366004612cfb565b61188a565b6040805192835260208301919091520161023a565b3480156105f957600080fd5b5061060d610608366004612c1b565b611905565b60405161023a9190600060a0820190508251151582526020830151602083015260408301516040830152606083015160608301526080830151608083015292915050565b34801561065d57600080fd5b506101fd61066c366004612b8a565b611996565b34801561067d57600080fd5b506101fd61068c366004612d46565b611b50565b34801561069d57600080fd5b506101fd6106ac366004612c1b565b611b6a565b3480156106bd57600080fd5b506101fd6106cc366004612b8a565b611c82565b3480156106dd57600080fd5b506000546001600160a01b031661054a565b3480156106fb57600080fd5b506101fd61200d565b34801561071057600080fd5b506101fd61071f366004612c1b565b61215e565b34801561073057600080fd5b50600254610230565b34801561074557600080fd5b506101fd610754366004612b8a565b61219c565b61076161238d565b6107696123be565b6001600160a01b0385166000908152601360205260409020805460ff166107ab5760405162461bcd60e51b81526004016107a290612d5f565b60405180910390fd5b6107b486612419565b600181018590556002810184905560048101829055600381018390556040805186815260208101869052908101849052606081018390526001600160a01b038716907f21b626117e8bba0f61d020ab20a54fc429f806331d2968a3679e02c1dafbfa1f906080015b60405180910390a2505050505050565b61083461238d565b61083c6123be565b61084583612419565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c0840152600b54811660e0840152600c548116610100840152600d54811661012084015286166000908152601490915291822060018101805492939192600e928792916108e1908490612da3565b92505081905550838260020160008282546108fc9190612da3565b92505081905550848160010160008282546109179190612da3565b92505081905550838160020160008282546109329190612da3565b909155505060c0830151604051630852cd8d60e31b8152600481018790526001600160a01b03909116906342966c6890602401600060405180830381600087803b15801561097f57600080fd5b505af1158015610993573d6000803e3d6000fd5b505060408051888152602081018890526001600160a01b038a1693507f2656bb10b0f54f3411f2bc3f1ffe6b9ba21347ac6aca35f61cc807f04f6cdd6392500161081c565b6109e061238d565b3360009081526013602052604090205460ff16610a0f5760405162461bcd60e51b81526004016107a290612d5f565b610a1833612419565b6040805161014081018252600480548252600554602080840191909152600654838501526007546060808501919091526008546001600160a01b03908116608080870191909152600954821660a080880191909152600a54831660c0880152600b54831660e08801908152600c548416610100890152600d548416610120890152336000818152601388528a81208b519485018c52805460ff1615158552600181810154868b0152600282810154878f0152600383015499870199909952908a0154958501958652918152601488528a90209351908401549584015491518a516301ca9e1160e71b81529a51999a93999498600e988d98610ca49894979096939094169363e54f08809380840193908290030181865afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b649190612db6565b89608001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ba6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bca9190612dcf565b60ff168a60a001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c339190612dcf565b60ff168b60e001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9c9190612dcf565b60ff166111f6565b1015610d185760405162461bcd60e51b815260206004820152603760248201527f52657175657374656420616d6f756e74206578636565647320616c6c6f77616260448201527f6c65206c69717569646974696f6e5468726573686f6c6400000000000000000060648201526084016107a2565b84826001016000828254610d2c9190612da3565b9250508190555084826005016000828254610d479190612df2565b9250508190555084816001016000828254610d629190612da3565b9250508190555084816004016000828254610d7d9190612df2565b909155505060405133907ff10b2a580b5ca98da11313b77317d62276a9c4eb2e9358fcf265626e05e7452a90610db69088908690612e05565b60405180910390a25050505050565b610dcd61238d565b3360009081526013602052604090205460ff16610dfc5760405162461bcd60e51b81526004016107a290612d5f565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a08401908152600a54821660c0850152600b54821660e0850152600c548216610100850152600d548216610120850152336000818152601490945294909220915192939192610e9392911690308661258f565b60a082015160c083015160405163095ea7b360e01b81526001600160a01b0391821660048201526024810186905291169063095ea7b3906044016020604051808303816000875af1158015610eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f109190612e4d565b5060c0820151604051639d3d156760e01b8152600481018590526001600160a01b0390911690639d3d1567906024016020604051808303816000875af1158015610f5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f829190612db6565b5082816001016000828254610f979190612df2565b9091555050600f8054849190600090610fb1908490612df2565b909155505060405133907f6412e73c734094aa05083b8630fa61510cdba375a6bca79600f96d6ead1c03b190610fea9086908590612e05565b60405180910390a2505050565b610fff61238d565b3360009081526013602052604090205460ff1661102e5760405162461bcd60e51b81526004016107a290612d5f565b61103733612419565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c0840152600b54811660e0840152600c548116610100840152600d54166101208301523360009081526014909152919091206002810154600e9084116110cb57836110d1565b81600201545b60808401519094506110ee906001600160a01b031633308761258f565b600082600201548360030154866111059190612e6f565b61110f9190612e9c565b9050600061111d8287612da3565b610120860151608087015191925061113f916001600160a01b031690836125fc565b858460020160008282546111539190612da3565b925050819055508184600301600082825461116e9190612da3565b92505081905550858360020160008282546111899190612da3565b909155505060405133907f68298fcd09d0a71648fd194c48ce9b1bd0a1b9541118f233e57725e22368cb369061081c9089908890612e05565b6000546001600160a01b031633146111ec5760405162461bcd60e51b81526004016107a290612ebe565b6111f461262d565b565b60008560000361120757508561125f565b6112118886612e6f565b6127108561121f8686612df2565b6112299190612da3565b61123490600a612fe3565b61123e9089612e6f565b6112489190612e6f565b6112529190612e9c565b61125c9088612da3565b90505b979650505050505050565b61129c6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b60035460005b600354811015611306576112dc600382815481106112c2576112c2612fef565b6000918252602090912001546001600160a01b031661145a565b60400151836040018181516112f19190612df2565b905250806112fe81613005565b9150506112a2565b5050600e548152600f5460208201526011546060820152601254608082015290565b61133061238d565b604080516101408101825260048054825260055460208301526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c08401819052600b54821660e0850152600c548216610100850152600d54909116610120840152925163e9ac06dd60e01b8152908101869052602481018590526044810184905290919063e9ac06dd906064016060604051808303816000875af11580156113ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611411919061301e565b505060408051858152602081018590529081018390527f6b49f967b7385832db14ab9924706721da8a69200a392331d471de8fc48421a99060600160405180910390a150505050565b61149a6040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0382166000818152601360209081526040808320815160a08082018452825460ff16151582526001808401548387019081526002808601548588019081526003808801546060808901919091526004988901546080808a01919091529c8c5260148b52898c208a5160c081018c52815464ffffffffff16808252978201549c81019c909c5293840154998b018a905290830154908a01529581015499880199909952600590980154918601919091529551915190959394938493611568939092909161188a565b845164ffffffffff168752602080860151908801526080808601519088015260a080860151908801526040850151919350915081906115a8908490612df2565b6115b29190612df2565b604086015260608301516115c7908290612df2565b60608601525092949350505050565b6115de6123be565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6116086123be565b6111f4600061268d565b6000546001600160a01b0316331461163c5760405162461bcd60e51b81526004016107a290612ebe565b6111f46126fe565b61164c61238d565b6116546123be565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c0840152600b54811660e0840152600c548116610100840152600d54811661012084015284166000908152601390915291909120805460ff16156117285760405162461bcd60e51b815260206004820152601860248201527f506f6f6c20616c726561647920696e697469616c697a6564000000000000000060448201526064016107a2565b805460ff191660019081178255604083015182820155606083015160028301556020830151600483015582516003830155600e805460009061176b908490612df2565b9091555050600380546001808201835560008390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b90910180546001600160a01b0319166001600160a01b03871690811790915560408051855460ff1615158152928501546020840152600285015490830152918301546060820152600483015460808201527fe931cc64a90f0a9d30870a204e4f7315edfd14b330c7c2e2a4831df538bdd8579060a001610fea565b6000856127108961182e85600a612fe3565b61183987600a612fe3565b6118439190612e6f565b61184e88600a612fe3565b6118588a8d612e6f565b6118629190612e6f565b61186c9190612e9c565b6118769190612e6f565b6118809190612e9c565b61125c9190612da3565b600080856118c46118bd6127106118ad6b033b2e3c9fd0803ce80000008a612e6f565b6118b79190612e9c565b86612747565b889061275d565b6118ce9190612da3565b9150856118f06118bd6127106118ad6b033b2e3c9fd0803ce800000089612e6f565b6118fa9190612da3565b905094509492505050565b6119396040518060a00160405280600015158152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b0316600090815260136020908152604091829020825160a081018452815460ff161515815260018201549281019290925260028101549282019290925260038201546060820152600490910154608082015290565b61199e61238d565b3360009081526013602052604090205460ff166119cd5760405162461bcd60e51b81526004016107a290612d5f565b60408051610140810182526004805482526005546020808401919091526006548385015260075460608401526008546001600160a01b039081166080850152600954811660a0850152600a54811660c0850152600b54811660e0850152600c548116610100850152600d541661012084015233600090815260149091529290922091820154909190600e90841115611ab15760405162461bcd60e51b815260206004820152602160248201527f496e73756666696369656e7420636c61696d61626c655553445420616d6f756e6044820152601d60fa1b60648201526084016107a2565b83826004016000828254611ac59190612da3565b9250508190555083816003016000828254611ae09190612da3565b90915550506101008301516080840151611b07916001600160a01b0390911690338761258f565b336001600160a01b03167f05438d07d1102052b382c9aa25699039323e56043f230fe828075e1cb9b884148584604051611b42929190612e05565b60405180910390a250505050565b611b586123be565b806004611b6582826130c5565b505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015611bb05750825b905060008267ffffffffffffffff166001148015611bcd5750303b155b905081158015611bdb575080155b15611bf95760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315611c2357845460ff60401b1916600160401b1785555b611c2c866127a1565b611c346127b2565b8315611c7a57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b611c8a61238d565b3360009081526013602052604090205460ff16611cb95760405162461bcd60e51b81526004016107a290612d5f565b611cc233612419565b60408051610140810182526004805482526005546020808401919091526006548385015260075460608401526008546001600160a01b039081166080850152600954811660a0850152600a54811660c0850152600b54811660e08501908152600c548216610100860152600d54821661012086015233600090815260138452868120601485529087902060038201546001820154600283015494518a516301ca9e1160e71b81529a51999a949993988c98611f0c98949793969395929094169363e54f088093808301939192908290030181865afa158015611da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcc9190612db6565b88608001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e329190612dcf565b60ff168960a001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9b9190612dcf565b60ff168a60e001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f049190612dcf565b60ff1661181c565b1015611f715760405162461bcd60e51b815260206004820152602e60248201527f52657175657374656420616d6f756e74206578636565647320616c6c6f77616260448201526d6c65206c6f616e546f56616c756560901b60648201526084016107a2565b83816002016000828254611f859190612df2565b9250508190555083816004016000828254611fa09190612df2565b909155505060108054859190600090611fba908490612df2565b909155505060118054859190600090611fd4908490612df2565b909155505060405133907f852d3292404d177009e4609d0e9a55c3a2e9f2711e5cc315cc4496c510305b3390611b429087908590612e05565b61201561238d565b61201d6123be565b604080516101408101825260048054825260055460208301526006548284015260075460608301526008546001600160a01b0390811660808401819052600954821660a0850152600a54821660c0850152600b54821660e0850152600c548216610100850152600d5490911661012084015292516370a0823160e01b8152309181019190915290916000916370a0823190602401602060405180830381865afa1580156120ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f29190612db6565b608083015190915061210e906001600160a01b031633836125fc565b80600160008282546121209190612da3565b909155505060405181815233907f14a6770a5ea104b5a2786ef29ae0b7519505f923bd33a6aa0e467649e2f10be69060200160405180910390a25050565b6121666123be565b6001600160a01b03811661219057604051631e4fbdf760e01b8152600060048201526024016107a2565b6121998161268d565b50565b6121a461238d565b3360009081526013602052604090205460ff166121d35760405162461bcd60e51b81526004016107a290612d5f565b60408051610140810182526004548152600580546020808401919091526006548385015260075460608401526008546001600160a01b039081166080850152600954811660a0850152600a54811660c0850152600b54811660e0850152600c548116610100850152600d541661012084015233600090815260149091529290922091820154909190600e908411156122a55760405162461bcd60e51b8152602060048201526015602482015274115e18d959590818db185a5b509510c81b1a5b5a5d605a1b60448201526064016107a2565b838260050160008282546122b99190612da3565b92505081905550838160040160008282546122d49190612da3565b909155505060c083015160405163db76009360e01b8152600481018690526001600160a01b039091169063db76009390602401600060405180830381600087803b15801561232157600080fd5b505af1158015612335573d6000803e3d6000fd5b50505060a084015161235291506001600160a01b031633866125fc565b336001600160a01b03167f1915eac8a68b84b4fd4adfc572edc237e3d32fee370e457a053dd065f10f9d418584604051611b42929190612e05565b6000805160206131ad8339815191525460ff16156111f45760405163d93c066560e01b815260040160405180910390fd5b336123f07f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146111f45760405163118cdaa760e01b81523360048201526024016107a2565b6001600160a01b0381166000818152601360209081526040808320815160a081018352815460ff16151581526001820154818501908152600280840154838601908152600385015460608501526004909401546080840152968652601490945291842094850154925190518554929594600e94909384936124a293909164ffffffffff1661188a565b855464ffffffffff19164264ffffffffff1617865590925090506124c68183612df2565b8460020160008282546124d99190612df2565b92505081905550808460030160008282546124f49190612df2565b9091555061250490508183612df2565b8360020160008282546125179190612df2565b9250508190555080600160008282546125309190612df2565b9250508190555080600260008282546125499190612df2565b909155505060408051838152602081018390526001600160a01b038816917f61face7ca496f195255e35210412a51f4bf6fec7227eab8a4246e3b0de547901910161081c565b6040516001600160a01b0384811660248301528381166044830152606482018390526125f69186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506127c2565b50505050565b6040516001600160a01b03838116602483015260448201839052611b6591859182169063a9059cbb906064016125c4565b612635612825565b6000805160206131ad833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b61270661238d565b6000805160206131ad833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2583361266f565b6000612754838342612855565b90505b92915050565b600081156b019d971e4fe8401e74000000198390048411151761277f57600080fd5b506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b6127a9612983565b612199816129cc565b6127ba612983565b6111f46129d4565b60006127d76001600160a01b038416836129f5565b905080516000141580156127fc5750808060200190518101906127fa9190612e4d565b155b15611b6557604051635274afe760e01b81526001600160a01b03841660048201526024016107a2565b6000805160206131ad8339815191525460ff166111f457604051638dfc202b60e01b815260040160405180910390fd5b60008061286964ffffffffff851684612da3565b905080600003612888576b033b2e3c9fd0803ce800000091505061297c565b600019810160008080600285116128a05760006128a5565b600285035b925066038882915c40006128b98a8061275d565b816128c6576128c6612e86565b0491506301e133806128d8838b61275d565b816128e5576128e5612e86565b0490506000826128f58688612e6f565b6128ff9190612e6f565b60029004905060008285612913888a612e6f565b61291d9190612e6f565b6129279190612e6f565b60069004905080826301e1338061293e8a8f612e6f565b6129489190612e9c565b61295e906b033b2e3c9fd0803ce8000000612df2565b6129689190612df2565b6129729190612df2565b9750505050505050505b9392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166111f457604051631afcd79f60e31b815260040160405180910390fd5b612166612983565b6129dc612983565b6000805160206131ad833981519152805460ff19169055565b60606127548383600084600080856001600160a01b03168486604051612a1b919061317d565b60006040518083038185875af1925050503d8060008114612a58576040519150601f19603f3d011682016040523d82523d6000602084013e612a5d565b606091505b5091509150612a6d868383612a77565b9695505050505050565b606082612a8c57612a8782612ad3565b61297c565b8151158015612aa357506001600160a01b0384163b155b15612acc57604051639996b31560e01b81526001600160a01b03851660048201526024016107a2565b508061297c565b805115612ae35780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b038116811461219957600080fd5b600080600080600060a08688031215612b2957600080fd5b8535612b3481612afc565b97602087013597506040870135966060810135965060800135945092505050565b600080600060608486031215612b6a57600080fd5b8335612b7581612afc565b95602085013595506040909401359392505050565b600060208284031215612b9c57600080fd5b5035919050565b600080600080600080600060e0888a031215612bbe57600080fd5b505085359760208701359750604087013596606081013596506080810135955060a0810135945060c0013592509050565b600080600060608486031215612c0457600080fd5b505081359360208301359350604090920135919050565b600060208284031215612c2d57600080fd5b813561297c81612afc565b600061014082019050825182526020830151602083015260408301516040830152606083015160608301526080830151612c7d60808401826001600160a01b03169052565b5060a0830151612c9860a08401826001600160a01b03169052565b5060c0830151612cb360c08401826001600160a01b03169052565b5060e0830151612cce60e08401826001600160a01b03169052565b50610100838101516001600160a01b03908116918401919091526101209384015116929091019190915290565b60008060008060808587031215612d1157600080fd5b843593506020850135925060408501359150606085013564ffffffffff81168114612d3b57600080fd5b939692955090935050565b60006101408284031215612d5957600080fd5b50919050565b602080825260149082015273141bdbdb081b9bdd081a5b9a5d1a585b1a5e995960621b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561275757612757612d8d565b600060208284031215612dc857600080fd5b5051919050565b600060208284031215612de157600080fd5b815160ff8116811461297c57600080fd5b8082018082111561275757612757612d8d565b918252805464ffffffffff166020830152600181015460408301526002810154606083015260038101546080830152600481015460a08301526005015460c082015260e00190565b600060208284031215612e5f57600080fd5b8151801515811461297c57600080fd5b808202811582820484141761275757612757612d8d565b634e487b7160e01b600052601260045260246000fd5b600082612eb957634e487b7160e01b600052601260045260246000fd5b500490565b60208082526021908201527f63616c6c6572206973206e6f7420656d657267656e6379436f6e74726f6c6c656040820152603960f91b606082015260800190565b600181815b80851115612f3a578160001904821115612f2057612f20612d8d565b80851615612f2d57918102915b93841c9390800290612f04565b509250929050565b600082612f5157506001612757565b81612f5e57506000612757565b8160018114612f745760028114612f7e57612f9a565b6001915050612757565b60ff841115612f8f57612f8f612d8d565b50506001821b612757565b5060208310610133831016604e8410600b8410161715612fbd575081810a612757565b612fc78383612eff565b8060001904821115612fdb57612fdb612d8d565b029392505050565b60006127548383612f42565b634e487b7160e01b600052603260045260246000fd5b60006001820161301757613017612d8d565b5060010190565b600080828403606081121561303257600080fd5b835192506040601f198201121561304857600080fd5b506040516040810181811067ffffffffffffffff8211171561307a57634e487b7160e01b600052604160045260246000fd5b60409081526020858101518352940151938101939093525092909150565b6000813561275781612afc565b80546001600160a01b0319166001600160a01b0392909216919091179055565b813581556020820135600182015560408201356002820155606082013560038201556130ff6130f660808401613098565b600483016130a5565b61311761310e60a08401613098565b600583016130a5565b61312f61312660c08401613098565b600683016130a5565b61314761313e60e08401613098565b600783016130a5565b6131606131576101008401613098565b600883016130a5565b6131796131706101208401613098565b600983016130a5565b5050565b6000825160005b8181101561319e5760208186018101518583015201613184565b50600092019182525091905056fecd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300a26469706673582212201bc7753c8c8a44c41f8578d7c32b9d8e5175a004ee5341d958e957360263b34464736f6c63430008140033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/partial_match/1/0xeb13f6d8Cd2f9A295fDAA5F1E7638D8ce6d3c5ED/","decoded_constructor_args":null,"compiler_version":"0.8.20+commit.a1b79de6","is_verified_via_verifier_alliance":false,"verified_at":"2024-08-21T16:11:55.723003Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801561001057600080fd5b50613202806100206000396000f3fe6080604052600436106101d85760003560e01c80638456cb5911610102578063b8d10cbb11610095578063cc144e6b11610064578063cc144e6b146106ef578063f2fde38b14610704578063f4b861df14610724578063f733f0481461073957600080fd5b8063b8d10cbb14610671578063c4d66de814610691578063c5ebeaec146106b1578063c993cc9d146106d157600080fd5b8063a3d77310116100d1578063a3d7731014610598578063a82cc1a0146105b8578063aec0da92146105ed578063b0f9006a1461065157600080fd5b80638456cb59146104fc5780638da5cb5b146105115780639049f9d214610562578063918f86741461058257600080fd5b80634867f3cf1161017a578063690ecf7211610149578063690ecf72146103725780636aa76b09146103e55780636ca7dc89146104c7578063715018a6146104e757600080fd5b80634867f3cf146102ab57806352a028d2146102cb5780635c975abb14610322578063639571341461035257600080fd5b80632e1a7d4d116101b65780632e1a7d4d146102435780633540302314610263578063371fd8e6146102835780633f4ba83a1461029657600080fd5b80630593f63d146101dd5780630710285c146101ff5780631d709e4e1461021f575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612b11565b610759565b005b34801561020b57600080fd5b506101fd61021a366004612b55565b61082c565b34801561022b57600080fd5b506001545b6040519081526020015b60405180910390f35b34801561024f57600080fd5b506101fd61025e366004612b8a565b6109d8565b34801561026f57600080fd5b506101fd61027e366004612b8a565b610dc5565b6101fd610291366004612b8a565b610ff7565b3480156102a257600080fd5b506101fd6111c2565b3480156102b757600080fd5b506102306102c6366004612ba3565b6111f6565b3480156102d757600080fd5b506102e061126a565b60405161023a9190600060a082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015292915050565b34801561032e57600080fd5b506000805160206131ad8339815191525460ff16604051901515815260200161023a565b34801561035e57600080fd5b506101fd61036d366004612bef565b611328565b34801561037e57600080fd5b5061039261038d366004612c1b565b61145a565b60405161023a9190600060c08201905064ffffffffff83511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b3480156103f157600080fd5b506104ba6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810191909152506040805161014081018252600454815260055460208201526006549181019190915260075460608201526008546001600160a01b039081166080830152600954811660a0830152600a54811660c0830152600b54811660e0830152600c548116610100830152600d541661012082015290565b60405161023a9190612c38565b3480156104d357600080fd5b506101fd6104e2366004612c1b565b6115d6565b3480156104f357600080fd5b506101fd611600565b34801561050857600080fd5b506101fd611612565b34801561051d57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b03909116815260200161023a565b34801561056e57600080fd5b506101fd61057d366004612c1b565b611644565b34801561058e57600080fd5b5061023061271081565b3480156105a457600080fd5b506102306105b3366004612ba3565b61181c565b3480156105c457600080fd5b506105d86105d3366004612cfb565b61188a565b6040805192835260208301919091520161023a565b3480156105f957600080fd5b5061060d610608366004612c1b565b611905565b60405161023a9190600060a0820190508251151582526020830151602083015260408301516040830152606083015160608301526080830151608083015292915050565b34801561065d57600080fd5b506101fd61066c366004612b8a565b611996565b34801561067d57600080fd5b506101fd61068c366004612d46565b611b50565b34801561069d57600080fd5b506101fd6106ac366004612c1b565b611b6a565b3480156106bd57600080fd5b506101fd6106cc366004612b8a565b611c82565b3480156106dd57600080fd5b506000546001600160a01b031661054a565b3480156106fb57600080fd5b506101fd61200d565b34801561071057600080fd5b506101fd61071f366004612c1b565b61215e565b34801561073057600080fd5b50600254610230565b34801561074557600080fd5b506101fd610754366004612b8a565b61219c565b61076161238d565b6107696123be565b6001600160a01b0385166000908152601360205260409020805460ff166107ab5760405162461bcd60e51b81526004016107a290612d5f565b60405180910390fd5b6107b486612419565b600181018590556002810184905560048101829055600381018390556040805186815260208101869052908101849052606081018390526001600160a01b038716907f21b626117e8bba0f61d020ab20a54fc429f806331d2968a3679e02c1dafbfa1f906080015b60405180910390a2505050505050565b61083461238d565b61083c6123be565b61084583612419565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c0840152600b54811660e0840152600c548116610100840152600d54811661012084015286166000908152601490915291822060018101805492939192600e928792916108e1908490612da3565b92505081905550838260020160008282546108fc9190612da3565b92505081905550848160010160008282546109179190612da3565b92505081905550838160020160008282546109329190612da3565b909155505060c0830151604051630852cd8d60e31b8152600481018790526001600160a01b03909116906342966c6890602401600060405180830381600087803b15801561097f57600080fd5b505af1158015610993573d6000803e3d6000fd5b505060408051888152602081018890526001600160a01b038a1693507f2656bb10b0f54f3411f2bc3f1ffe6b9ba21347ac6aca35f61cc807f04f6cdd6392500161081c565b6109e061238d565b3360009081526013602052604090205460ff16610a0f5760405162461bcd60e51b81526004016107a290612d5f565b610a1833612419565b6040805161014081018252600480548252600554602080840191909152600654838501526007546060808501919091526008546001600160a01b03908116608080870191909152600954821660a080880191909152600a54831660c0880152600b54831660e08801908152600c548416610100890152600d548416610120890152336000818152601388528a81208b519485018c52805460ff1615158552600181810154868b0152600282810154878f0152600383015499870199909952908a0154958501958652918152601488528a90209351908401549584015491518a516301ca9e1160e71b81529a51999a93999498600e988d98610ca49894979096939094169363e54f08809380840193908290030181865afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b649190612db6565b89608001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ba6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bca9190612dcf565b60ff168a60a001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c339190612dcf565b60ff168b60e001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9c9190612dcf565b60ff166111f6565b1015610d185760405162461bcd60e51b815260206004820152603760248201527f52657175657374656420616d6f756e74206578636565647320616c6c6f77616260448201527f6c65206c69717569646974696f6e5468726573686f6c6400000000000000000060648201526084016107a2565b84826001016000828254610d2c9190612da3565b9250508190555084826005016000828254610d479190612df2565b9250508190555084816001016000828254610d629190612da3565b9250508190555084816004016000828254610d7d9190612df2565b909155505060405133907ff10b2a580b5ca98da11313b77317d62276a9c4eb2e9358fcf265626e05e7452a90610db69088908690612e05565b60405180910390a25050505050565b610dcd61238d565b3360009081526013602052604090205460ff16610dfc5760405162461bcd60e51b81526004016107a290612d5f565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a08401908152600a54821660c0850152600b54821660e0850152600c548216610100850152600d548216610120850152336000818152601490945294909220915192939192610e9392911690308661258f565b60a082015160c083015160405163095ea7b360e01b81526001600160a01b0391821660048201526024810186905291169063095ea7b3906044016020604051808303816000875af1158015610eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f109190612e4d565b5060c0820151604051639d3d156760e01b8152600481018590526001600160a01b0390911690639d3d1567906024016020604051808303816000875af1158015610f5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f829190612db6565b5082816001016000828254610f979190612df2565b9091555050600f8054849190600090610fb1908490612df2565b909155505060405133907f6412e73c734094aa05083b8630fa61510cdba375a6bca79600f96d6ead1c03b190610fea9086908590612e05565b60405180910390a2505050565b610fff61238d565b3360009081526013602052604090205460ff1661102e5760405162461bcd60e51b81526004016107a290612d5f565b61103733612419565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c0840152600b54811660e0840152600c548116610100840152600d54166101208301523360009081526014909152919091206002810154600e9084116110cb57836110d1565b81600201545b60808401519094506110ee906001600160a01b031633308761258f565b600082600201548360030154866111059190612e6f565b61110f9190612e9c565b9050600061111d8287612da3565b610120860151608087015191925061113f916001600160a01b031690836125fc565b858460020160008282546111539190612da3565b925050819055508184600301600082825461116e9190612da3565b92505081905550858360020160008282546111899190612da3565b909155505060405133907f68298fcd09d0a71648fd194c48ce9b1bd0a1b9541118f233e57725e22368cb369061081c9089908890612e05565b6000546001600160a01b031633146111ec5760405162461bcd60e51b81526004016107a290612ebe565b6111f461262d565b565b60008560000361120757508561125f565b6112118886612e6f565b6127108561121f8686612df2565b6112299190612da3565b61123490600a612fe3565b61123e9089612e6f565b6112489190612e6f565b6112529190612e9c565b61125c9088612da3565b90505b979650505050505050565b61129c6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b60035460005b600354811015611306576112dc600382815481106112c2576112c2612fef565b6000918252602090912001546001600160a01b031661145a565b60400151836040018181516112f19190612df2565b905250806112fe81613005565b9150506112a2565b5050600e548152600f5460208201526011546060820152601254608082015290565b61133061238d565b604080516101408101825260048054825260055460208301526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c08401819052600b54821660e0850152600c548216610100850152600d54909116610120840152925163e9ac06dd60e01b8152908101869052602481018590526044810184905290919063e9ac06dd906064016060604051808303816000875af11580156113ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611411919061301e565b505060408051858152602081018590529081018390527f6b49f967b7385832db14ab9924706721da8a69200a392331d471de8fc48421a99060600160405180910390a150505050565b61149a6040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b0382166000818152601360209081526040808320815160a08082018452825460ff16151582526001808401548387019081526002808601548588019081526003808801546060808901919091526004988901546080808a01919091529c8c5260148b52898c208a5160c081018c52815464ffffffffff16808252978201549c81019c909c5293840154998b018a905290830154908a01529581015499880199909952600590980154918601919091529551915190959394938493611568939092909161188a565b845164ffffffffff168752602080860151908801526080808601519088015260a080860151908801526040850151919350915081906115a8908490612df2565b6115b29190612df2565b604086015260608301516115c7908290612df2565b60608601525092949350505050565b6115de6123be565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6116086123be565b6111f4600061268d565b6000546001600160a01b0316331461163c5760405162461bcd60e51b81526004016107a290612ebe565b6111f46126fe565b61164c61238d565b6116546123be565b604080516101408101825260045481526005546020808301919091526006548284015260075460608301526008546001600160a01b039081166080840152600954811660a0840152600a54811660c0840152600b54811660e0840152600c548116610100840152600d54811661012084015284166000908152601390915291909120805460ff16156117285760405162461bcd60e51b815260206004820152601860248201527f506f6f6c20616c726561647920696e697469616c697a6564000000000000000060448201526064016107a2565b805460ff191660019081178255604083015182820155606083015160028301556020830151600483015582516003830155600e805460009061176b908490612df2565b9091555050600380546001808201835560008390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b90910180546001600160a01b0319166001600160a01b03871690811790915560408051855460ff1615158152928501546020840152600285015490830152918301546060820152600483015460808201527fe931cc64a90f0a9d30870a204e4f7315edfd14b330c7c2e2a4831df538bdd8579060a001610fea565b6000856127108961182e85600a612fe3565b61183987600a612fe3565b6118439190612e6f565b61184e88600a612fe3565b6118588a8d612e6f565b6118629190612e6f565b61186c9190612e9c565b6118769190612e6f565b6118809190612e9c565b61125c9190612da3565b600080856118c46118bd6127106118ad6b033b2e3c9fd0803ce80000008a612e6f565b6118b79190612e9c565b86612747565b889061275d565b6118ce9190612da3565b9150856118f06118bd6127106118ad6b033b2e3c9fd0803ce800000089612e6f565b6118fa9190612da3565b905094509492505050565b6119396040518060a00160405280600015158152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b0316600090815260136020908152604091829020825160a081018452815460ff161515815260018201549281019290925260028101549282019290925260038201546060820152600490910154608082015290565b61199e61238d565b3360009081526013602052604090205460ff166119cd5760405162461bcd60e51b81526004016107a290612d5f565b60408051610140810182526004805482526005546020808401919091526006548385015260075460608401526008546001600160a01b039081166080850152600954811660a0850152600a54811660c0850152600b54811660e0850152600c548116610100850152600d541661012084015233600090815260149091529290922091820154909190600e90841115611ab15760405162461bcd60e51b815260206004820152602160248201527f496e73756666696369656e7420636c61696d61626c655553445420616d6f756e6044820152601d60fa1b60648201526084016107a2565b83826004016000828254611ac59190612da3565b9250508190555083816003016000828254611ae09190612da3565b90915550506101008301516080840151611b07916001600160a01b0390911690338761258f565b336001600160a01b03167f05438d07d1102052b382c9aa25699039323e56043f230fe828075e1cb9b884148584604051611b42929190612e05565b60405180910390a250505050565b611b586123be565b806004611b6582826130c5565b505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015611bb05750825b905060008267ffffffffffffffff166001148015611bcd5750303b155b905081158015611bdb575080155b15611bf95760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315611c2357845460ff60401b1916600160401b1785555b611c2c866127a1565b611c346127b2565b8315611c7a57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b611c8a61238d565b3360009081526013602052604090205460ff16611cb95760405162461bcd60e51b81526004016107a290612d5f565b611cc233612419565b60408051610140810182526004805482526005546020808401919091526006548385015260075460608401526008546001600160a01b039081166080850152600954811660a0850152600a54811660c0850152600b54811660e08501908152600c548216610100860152600d54821661012086015233600090815260138452868120601485529087902060038201546001820154600283015494518a516301ca9e1160e71b81529a51999a949993988c98611f0c98949793969395929094169363e54f088093808301939192908290030181865afa158015611da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcc9190612db6565b88608001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e329190612dcf565b60ff168960a001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9b9190612dcf565b60ff168a60e001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f049190612dcf565b60ff1661181c565b1015611f715760405162461bcd60e51b815260206004820152602e60248201527f52657175657374656420616d6f756e74206578636565647320616c6c6f77616260448201526d6c65206c6f616e546f56616c756560901b60648201526084016107a2565b83816002016000828254611f859190612df2565b9250508190555083816004016000828254611fa09190612df2565b909155505060108054859190600090611fba908490612df2565b909155505060118054859190600090611fd4908490612df2565b909155505060405133907f852d3292404d177009e4609d0e9a55c3a2e9f2711e5cc315cc4496c510305b3390611b429087908590612e05565b61201561238d565b61201d6123be565b604080516101408101825260048054825260055460208301526006548284015260075460608301526008546001600160a01b0390811660808401819052600954821660a0850152600a54821660c0850152600b54821660e0850152600c548216610100850152600d5490911661012084015292516370a0823160e01b8152309181019190915290916000916370a0823190602401602060405180830381865afa1580156120ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f29190612db6565b608083015190915061210e906001600160a01b031633836125fc565b80600160008282546121209190612da3565b909155505060405181815233907f14a6770a5ea104b5a2786ef29ae0b7519505f923bd33a6aa0e467649e2f10be69060200160405180910390a25050565b6121666123be565b6001600160a01b03811661219057604051631e4fbdf760e01b8152600060048201526024016107a2565b6121998161268d565b50565b6121a461238d565b3360009081526013602052604090205460ff166121d35760405162461bcd60e51b81526004016107a290612d5f565b60408051610140810182526004548152600580546020808401919091526006548385015260075460608401526008546001600160a01b039081166080850152600954811660a0850152600a54811660c0850152600b54811660e0850152600c548116610100850152600d541661012084015233600090815260149091529290922091820154909190600e908411156122a55760405162461bcd60e51b8152602060048201526015602482015274115e18d959590818db185a5b509510c81b1a5b5a5d605a1b60448201526064016107a2565b838260050160008282546122b99190612da3565b92505081905550838160040160008282546122d49190612da3565b909155505060c083015160405163db76009360e01b8152600481018690526001600160a01b039091169063db76009390602401600060405180830381600087803b15801561232157600080fd5b505af1158015612335573d6000803e3d6000fd5b50505060a084015161235291506001600160a01b031633866125fc565b336001600160a01b03167f1915eac8a68b84b4fd4adfc572edc237e3d32fee370e457a053dd065f10f9d418584604051611b42929190612e05565b6000805160206131ad8339815191525460ff16156111f45760405163d93c066560e01b815260040160405180910390fd5b336123f07f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146111f45760405163118cdaa760e01b81523360048201526024016107a2565b6001600160a01b0381166000818152601360209081526040808320815160a081018352815460ff16151581526001820154818501908152600280840154838601908152600385015460608501526004909401546080840152968652601490945291842094850154925190518554929594600e94909384936124a293909164ffffffffff1661188a565b855464ffffffffff19164264ffffffffff1617865590925090506124c68183612df2565b8460020160008282546124d99190612df2565b92505081905550808460030160008282546124f49190612df2565b9091555061250490508183612df2565b8360020160008282546125179190612df2565b9250508190555080600160008282546125309190612df2565b9250508190555080600260008282546125499190612df2565b909155505060408051838152602081018390526001600160a01b038816917f61face7ca496f195255e35210412a51f4bf6fec7227eab8a4246e3b0de547901910161081c565b6040516001600160a01b0384811660248301528381166044830152606482018390526125f69186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506127c2565b50505050565b6040516001600160a01b03838116602483015260448201839052611b6591859182169063a9059cbb906064016125c4565b612635612825565b6000805160206131ad833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b61270661238d565b6000805160206131ad833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2583361266f565b6000612754838342612855565b90505b92915050565b600081156b019d971e4fe8401e74000000198390048411151761277f57600080fd5b506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b6127a9612983565b612199816129cc565b6127ba612983565b6111f46129d4565b60006127d76001600160a01b038416836129f5565b905080516000141580156127fc5750808060200190518101906127fa9190612e4d565b155b15611b6557604051635274afe760e01b81526001600160a01b03841660048201526024016107a2565b6000805160206131ad8339815191525460ff166111f457604051638dfc202b60e01b815260040160405180910390fd5b60008061286964ffffffffff851684612da3565b905080600003612888576b033b2e3c9fd0803ce800000091505061297c565b600019810160008080600285116128a05760006128a5565b600285035b925066038882915c40006128b98a8061275d565b816128c6576128c6612e86565b0491506301e133806128d8838b61275d565b816128e5576128e5612e86565b0490506000826128f58688612e6f565b6128ff9190612e6f565b60029004905060008285612913888a612e6f565b61291d9190612e6f565b6129279190612e6f565b60069004905080826301e1338061293e8a8f612e6f565b6129489190612e9c565b61295e906b033b2e3c9fd0803ce8000000612df2565b6129689190612df2565b6129729190612df2565b9750505050505050505b9392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166111f457604051631afcd79f60e31b815260040160405180910390fd5b612166612983565b6129dc612983565b6000805160206131ad833981519152805460ff19169055565b60606127548383600084600080856001600160a01b03168486604051612a1b919061317d565b60006040518083038185875af1925050503d8060008114612a58576040519150601f19603f3d011682016040523d82523d6000602084013e612a5d565b606091505b5091509150612a6d868383612a77565b9695505050505050565b606082612a8c57612a8782612ad3565b61297c565b8151158015612aa357506001600160a01b0384163b155b15612acc57604051639996b31560e01b81526001600160a01b03851660048201526024016107a2565b508061297c565b805115612ae35780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b038116811461219957600080fd5b600080600080600060a08688031215612b2957600080fd5b8535612b3481612afc565b97602087013597506040870135966060810135965060800135945092505050565b600080600060608486031215612b6a57600080fd5b8335612b7581612afc565b95602085013595506040909401359392505050565b600060208284031215612b9c57600080fd5b5035919050565b600080600080600080600060e0888a031215612bbe57600080fd5b505085359760208701359750604087013596606081013596506080810135955060a0810135945060c0013592509050565b600080600060608486031215612c0457600080fd5b505081359360208301359350604090920135919050565b600060208284031215612c2d57600080fd5b813561297c81612afc565b600061014082019050825182526020830151602083015260408301516040830152606083015160608301526080830151612c7d60808401826001600160a01b03169052565b5060a0830151612c9860a08401826001600160a01b03169052565b5060c0830151612cb360c08401826001600160a01b03169052565b5060e0830151612cce60e08401826001600160a01b03169052565b50610100838101516001600160a01b03908116918401919091526101209384015116929091019190915290565b60008060008060808587031215612d1157600080fd5b843593506020850135925060408501359150606085013564ffffffffff81168114612d3b57600080fd5b939692955090935050565b60006101408284031215612d5957600080fd5b50919050565b602080825260149082015273141bdbdb081b9bdd081a5b9a5d1a585b1a5e995960621b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561275757612757612d8d565b600060208284031215612dc857600080fd5b5051919050565b600060208284031215612de157600080fd5b815160ff8116811461297c57600080fd5b8082018082111561275757612757612d8d565b918252805464ffffffffff166020830152600181015460408301526002810154606083015260038101546080830152600481015460a08301526005015460c082015260e00190565b600060208284031215612e5f57600080fd5b8151801515811461297c57600080fd5b808202811582820484141761275757612757612d8d565b634e487b7160e01b600052601260045260246000fd5b600082612eb957634e487b7160e01b600052601260045260246000fd5b500490565b60208082526021908201527f63616c6c6572206973206e6f7420656d657267656e6379436f6e74726f6c6c656040820152603960f91b606082015260800190565b600181815b80851115612f3a578160001904821115612f2057612f20612d8d565b80851615612f2d57918102915b93841c9390800290612f04565b509250929050565b600082612f5157506001612757565b81612f5e57506000612757565b8160018114612f745760028114612f7e57612f9a565b6001915050612757565b60ff841115612f8f57612f8f612d8d565b50506001821b612757565b5060208310610133831016604e8410600b8410161715612fbd575081810a612757565b612fc78383612eff565b8060001904821115612fdb57612fdb612d8d565b029392505050565b60006127548383612f42565b634e487b7160e01b600052603260045260246000fd5b60006001820161301757613017612d8d565b5060010190565b600080828403606081121561303257600080fd5b835192506040601f198201121561304857600080fd5b506040516040810181811067ffffffffffffffff8211171561307a57634e487b7160e01b600052604160045260246000fd5b60409081526020858101518352940151938101939093525092909150565b6000813561275781612afc565b80546001600160a01b0319166001600160a01b0392909216919091179055565b813581556020820135600182015560408201356002820155606082013560038201556130ff6130f660808401613098565b600483016130a5565b61311761310e60a08401613098565b600583016130a5565b61312f61312660c08401613098565b600683016130a5565b61314761313e60e08401613098565b600783016130a5565b6131606131576101008401613098565b600883016130a5565b6131796131706101208401613098565b600983016130a5565b5050565b6000825160005b8181101561319e5760208186018101518583015201613184565b50600092019182525091905056fecd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300a26469706673582212201bc7753c8c8a44c41f8578d7c32b9d8e5175a004ee5341d958e957360263b34464736f6c63430008140033","name":"PoolManager","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint40","name":"timeStampIndex","type":"uint40"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"debtToProtocol","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"indexed":false,"internalType":"struct DataTypes.UserPoolReserveInformation","name":"userPoolReserveInformation","type":"tuple"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint40","name":"timeStampIndex","type":"uint40"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"debtToProtocol","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"indexed":false,"internalType":"struct DataTypes.UserPoolReserveInformation","name":"userPoolReserveInformation","type":"tuple"}],"name":"ClaimBTC","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint40","name":"timeStampIndex","type":"uint40"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"debtToProtocol","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"indexed":false,"internalType":"struct DataTypes.UserPoolReserveInformation","name":"userPoolReserveInformation","type":"tuple"}],"name":"ClaimUSDT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debt","type":"uint256"}],"name":"Liquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"components":[{"internalType":"bool","name":"init","type":"bool"},{"internalType":"uint256","name":"poolInterestRate","type":"uint256"},{"internalType":"uint256","name":"protocolInterestRate","type":"uint256"},{"internalType":"uint256","name":"loanToValue","type":"uint256"},{"internalType":"uint256","name":"liquidationThreshold","type":"uint256"}],"indexed":false,"internalType":"struct DataTypes.UserPoolConfig","name":"userPoolConfig","type":"tuple"}],"name":"PoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ProtocolEarningsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint40","name":"timeStampIndex","type":"uint40"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"debtToProtocol","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"indexed":false,"internalType":"struct DataTypes.UserPoolReserveInformation","name":"userPoolReserveInformation","type":"tuple"}],"name":"Repay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"depositTxid","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"outputIndex","type":"uint256"}],"name":"RequestMintFBTC0","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint40","name":"timeStampIndex","type":"uint40"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"debtToProtocol","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"indexed":false,"internalType":"struct DataTypes.UserPoolReserveInformation","name":"userPoolReserveInformation","type":"tuple"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeForPool","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeForProtocol","type":"uint256"}],"name":"UpdateState","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"poolInterestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolInterestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanToValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationThreshold","type":"uint256"}],"name":"UserPoolConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint40","name":"timeStampIndex","type":"uint40"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"debtToProtocol","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"indexed":false,"internalType":"struct DataTypes.UserPoolReserveInformation","name":"userPoolReserveInformation","type":"tuple"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"poolInterestRate","type":"uint256"},{"internalType":"uint256","name":"protocolInterestRate","type":"uint256"},{"internalType":"uint40","name":"timeStampIndex","type":"uint40"}],"name":"calculateAccumulatedDebt","outputs":[{"internalType":"uint256","name":"feeForPool","type":"uint256"},{"internalType":"uint256","name":"feeForProtocol","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanToValue","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"FBTC0Price","type":"uint256"},{"internalType":"uint256","name":"USDTDecimal","type":"uint256"},{"internalType":"uint256","name":"FBTC0Decimal","type":"uint256"},{"internalType":"uint256","name":"oracleDecimal","type":"uint256"}],"name":"calculateMaxBorrowAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidationThreshold","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"FBTC0Price","type":"uint256"},{"internalType":"uint256","name":"USDTDecimal","type":"uint256"},{"internalType":"uint256","name":"FBTC0Decimal","type":"uint256"},{"internalType":"uint256","name":"oracleDecimal","type":"uint256"}],"name":"calculateMaxWithdrawAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimBTC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimProtocolEarnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimUSDT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"createPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getEmergencyController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolManagerConfig","outputs":[{"components":[{"internalType":"uint256","name":"DEFAULT_LTV","type":"uint256"},{"internalType":"uint256","name":"DEFAULT_LIQUIDATION_THRESHOLD","type":"uint256"},{"internalType":"uint256","name":"DEFAULT_POOL_INTEREST_RATE","type":"uint256"},{"internalType":"uint256","name":"DEFAULT_PROTOCOL_INTEREST_RATE","type":"uint256"},{"internalType":"contract IERC20","name":"USDT","type":"address"},{"internalType":"contract IERC20","name":"FBTC0","type":"address"},{"internalType":"contract IFBTC1","name":"FBTC1","type":"address"},{"internalType":"contract IFBTCOracle","name":"FBTCOracle","type":"address"},{"internalType":"address","name":"AvalonUSDTVault","type":"address"},{"internalType":"address","name":"AntaphaUSDTVault","type":"address"}],"internalType":"struct DataTypes.PoolManagerConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolManagerReserveInformation","outputs":[{"components":[{"internalType":"uint256","name":"userAmount","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"internalType":"struct DataTypes.PoolManagerReserveInformation","name":"poolManagerReserveInfor","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolProfitAccumulate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolProfitUnclaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserPoolConfig","outputs":[{"components":[{"internalType":"bool","name":"init","type":"bool"},{"internalType":"uint256","name":"poolInterestRate","type":"uint256"},{"internalType":"uint256","name":"protocolInterestRate","type":"uint256"},{"internalType":"uint256","name":"loanToValue","type":"uint256"},{"internalType":"uint256","name":"liquidationThreshold","type":"uint256"}],"internalType":"struct DataTypes.UserPoolConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserPoolReserveInformation","outputs":[{"components":[{"internalType":"uint40","name":"timeStampIndex","type":"uint40"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"debtToProtocol","type":"uint256"},{"internalType":"uint256","name":"claimableUSDT","type":"uint256"},{"internalType":"uint256","name":"claimableBTC","type":"uint256"}],"internalType":"struct DataTypes.UserPoolReserveInformation","name":"reserveAfterUpdateDebt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"collateralDecrease","type":"uint256"},{"internalType":"uint256","name":"debtDecrease","type":"uint256"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","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":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"depositTxid","type":"bytes32"},{"internalType":"uint256","name":"outputIndex","type":"uint256"}],"name":"requestMintFBTC0","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"emergencyController","type":"address"}],"name":"setEmergencyController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"DEFAULT_LTV","type":"uint256"},{"internalType":"uint256","name":"DEFAULT_LIQUIDATION_THRESHOLD","type":"uint256"},{"internalType":"uint256","name":"DEFAULT_POOL_INTEREST_RATE","type":"uint256"},{"internalType":"uint256","name":"DEFAULT_PROTOCOL_INTEREST_RATE","type":"uint256"},{"internalType":"contract IERC20","name":"USDT","type":"address"},{"internalType":"contract IERC20","name":"FBTC0","type":"address"},{"internalType":"contract IFBTC1","name":"FBTC1","type":"address"},{"internalType":"contract IFBTCOracle","name":"FBTCOracle","type":"address"},{"internalType":"address","name":"AvalonUSDTVault","type":"address"},{"internalType":"address","name":"AntaphaUSDTVault","type":"address"}],"internalType":"struct DataTypes.PoolManagerConfig","name":"configInput","type":"tuple"}],"name":"setPoolManagerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolInterestRate","type":"uint256"},{"internalType":"uint256","name":"protocolInterestRate","type":"uint256"},{"internalType":"uint256","name":"loanToValue","type":"uint256"},{"internalType":"uint256","name":"liquidationThreshold","type":"uint256"}],"name":"setUserPoolConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":null}