creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20PermitUpgradeable {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n    using AddressUpgradeable for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20PermitUpgradeable token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCastUpgradeable {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "contracts/_interfaces/buttonwood/IBondController.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { ITranche } from \"./ITranche.sol\";\n\ninterface IBondController {\n    function collateralToken() external view returns (address);\n\n    function maturityDate() external view returns (uint256);\n\n    function creationDate() external view returns (uint256);\n\n    function totalDebt() external view returns (uint256);\n\n    function feeBps() external view returns (uint256);\n\n    function isMature() external view returns (bool);\n\n    function tranches(uint256 i) external view returns (ITranche token, uint256 ratio);\n\n    function trancheCount() external view returns (uint256 count);\n\n    function trancheTokenAddresses(ITranche token) external view returns (bool);\n\n    function deposit(uint256 amount) external;\n\n    function redeem(uint256[] memory amounts) external;\n\n    function mature() external;\n\n    function redeemMature(address tranche, uint256 amount) external;\n}\n"
      },
      "contracts/_interfaces/buttonwood/ITranche.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\ninterface ITranche is IERC20Upgradeable {\n    function bond() external view returns (address);\n}\n"
      },
      "contracts/_interfaces/CommonTypes.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nstruct TokenAmount {\n    /// @notice The asset token redeemed.\n    IERC20Upgradeable token;\n    /// @notice The amount redeemed.\n    uint256 amount;\n}\n\n/// @notice The system subscription parameters.\nstruct SubscriptionParams {\n    /// @notice The current TVL of perp denominated in the underlying.\n    uint256 perpTVL;\n    /// @notice The current TVL of the vault denominated in the underlying.\n    uint256 vaultTVL;\n    /// @notice The tranche ratio of seniors accepted by perp.\n    uint256 seniorTR;\n}\n\nstruct RolloverData {\n    /// @notice The amount of tokens rolled out.\n    uint256 tokenOutAmt;\n    /// @notice The amount of trancheIn tokens rolled in.\n    uint256 trancheInAmt;\n}\n"
      },
      "contracts/_interfaces/IBondIssuer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { IBondController } from \"./buttonwood/IBondController.sol\";\n\ninterface IBondIssuer {\n    /// @notice Event emitted when a new bond is issued by the issuer.\n    /// @param bond The newly issued bond.\n    event BondIssued(IBondController bond);\n\n    /// @notice Event emitted when a bond has matured.\n    /// @param bond The matured bond.\n    event BondMature(IBondController bond);\n\n    /// @notice The address of the underlying collateral token to be used for issued bonds.\n    /// @return Address of the collateral token.\n    function collateral() external view returns (address);\n\n    /// @notice Invokes `mature` on issued active bonds.\n    function matureActive() external;\n\n    /// @notice Issues a new bond if sufficient time has elapsed since the last issue.\n    function issue() external;\n\n    /// @notice Checks if a given bond has been issued by the issuer.\n    /// @param bond Address of the bond to check.\n    /// @return if the bond has been issued by the issuer.\n    function isInstance(IBondController bond) external view returns (bool);\n\n    /// @notice Fetches the most recently issued bond.\n    /// @return Address of the most recent bond.\n    function getLatestBond() external returns (IBondController);\n\n    /// @notice Returns the total number of bonds issued by this issuer.\n    /// @return Number of bonds.\n    function issuedCount() external view returns (uint256);\n\n    /// @notice The bond address from the issued list by index.\n    /// @param index The index of the bond in the issued list.\n    /// @return Address of the bond.\n    function issuedBondAt(uint256 index) external view returns (IBondController);\n}\n"
      },
      "contracts/_interfaces/IFeePolicy.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { SubscriptionParams } from \"./CommonTypes.sol\";\n\ninterface IFeePolicy {\n    /// @return The percentage of the mint perp tokens to be charged as fees,\n    ///         as a fixed-point number with {DECIMALS} decimal places.\n    function computePerpMintFeePerc() external view returns (uint256);\n\n    /// @return The percentage of the burnt perp tokens to be charged as fees,\n    ///         as a fixed-point number with {DECIMALS} decimal places.\n    function computePerpBurnFeePerc() external view returns (uint256);\n\n    /// @param dr The current system deviation ratio.\n    /// @return The applied exchange rate adjustment between tranches into perp and\n    ///         tokens out of perp during a rollover,\n    ///         as a fixed-point number with {DECIMALS} decimal places.\n    /// @dev - A fee of 0%, implies the rollover exchange rate is unaltered.\n    ///         example) 100 tranchesIn for 100 tranchesOut\n    ///      - A fee of 1%, implies the exchange rate is adjusted in favor of tranchesIn.\n    ///         example) 100 tranchesIn for 99 tranchesOut; i.e) perp enrichment\n    ///      - A fee of -1%, implies the exchange rate is adjusted in favor of tranchesOut.\n    ///         example) 99 tranchesIn for 100 tranchesOut\n    function computePerpRolloverFeePerc(uint256 dr) external view returns (int256);\n\n    /// @return The percentage of the mint vault note amount to be charged as fees,\n    ///         as a fixed-point number with {DECIMALS} decimal places.\n    function computeVaultMintFeePerc() external view returns (uint256);\n\n    /// @return The percentage of the burnt vault note amount to be charged as fees,\n    ///         as a fixed-point number with {DECIMALS} decimal places.\n    function computeVaultBurnFeePerc() external view returns (uint256);\n\n    /// @param dr The current system deviation ratio.\n    /// @param dr_ The deviation ratio of the system after the operation is complete.\n    /// @return The percentage of perp tokens out to be charged as swap fees by the vault,\n    ///         as a fixed-point numbers with {DECIMALS} decimal places.\n    function computeUnderlyingToPerpVaultSwapFeePerc(uint256 dr, uint256 dr_) external view returns (uint256);\n\n    /// @param dr The current system deviation ratio.\n    /// @param dr_ The deviation ratio of the system after the operation is complete.\n    /// @return The percentage of underlying tokens out to be charged as swap fees by the vault,\n    ///         as a fixed-point numbers with {DECIMALS} decimal places.\n    function computePerpToUnderlyingVaultSwapFeePerc(uint256 dr, uint256 dr_) external view returns (uint256);\n\n    /// @return Number of decimals representing a multiplier of 1.0. So, 100% = 1*10**decimals.\n    function decimals() external view returns (uint8);\n\n    /// @param s The subscription parameters of both the perp and vault systems.\n    /// @return The deviation ratio given the system subscription parameters.\n    function computeDeviationRatio(SubscriptionParams memory s) external view returns (uint256);\n}\n"
      },
      "contracts/_interfaces/IPerpetualTranche.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { IBondIssuer } from \"./IBondIssuer.sol\";\nimport { IFeePolicy } from \"./IFeePolicy.sol\";\nimport { IBondController } from \"./buttonwood/IBondController.sol\";\nimport { ITranche } from \"./buttonwood/ITranche.sol\";\nimport { IRolloverVault } from \"./IRolloverVault.sol\";\nimport { TokenAmount, RolloverData } from \"./CommonTypes.sol\";\n\ninterface IPerpetualTranche is IERC20Upgradeable {\n    //--------------------------------------------------------------------------\n    // Events\n\n    /// @notice Event emitted the reserve's current token balance is recorded after change.\n    /// @param token Address of token.\n    /// @param balance The recorded ERC-20 balance of the token held by the reserve.\n    event ReserveSynced(IERC20Upgradeable token, uint256 balance);\n\n    /// @notice Event emitted when the active deposit bond is updated.\n    /// @param bond Address of the new deposit bond.\n    event UpdatedDepositBond(IBondController bond);\n\n    //--------------------------------------------------------------------------\n    // Methods\n\n    /// @notice Deposits tranche tokens into the system and mint perp tokens.\n    /// @param trancheIn The address of the tranche token to be deposited.\n    /// @param trancheInAmt The amount of tranche tokens deposited.\n    /// @return The amount of perp tokens minted.\n    function deposit(ITranche trancheIn, uint256 trancheInAmt) external returns (uint256);\n\n    /// @notice Burn perp tokens and redeem the share of reserve assets.\n    /// @param perpAmtBurnt The amount of perp tokens burnt from the caller.\n    /// @return tokensOut The list of reserve tokens and amounts redeemed.\n    function redeem(uint256 perpAmtBurnt) external returns (TokenAmount[] memory tokensOut);\n\n    /// @notice Rotates newer tranches in for reserve tokens.\n    /// @param trancheIn The tranche token deposited.\n    /// @param tokenOut The reserve token to be redeemed.\n    /// @param trancheInAmt The amount of trancheIn tokens deposited.\n    /// @return r The rollover amounts in various denominations.\n    function rollover(\n        ITranche trancheIn,\n        IERC20Upgradeable tokenOut,\n        uint256 trancheInAmt\n    ) external returns (RolloverData memory r);\n\n    /// @notice External contract that stores a predefined bond config and frequency,\n    ///         and issues new bonds when poked.\n    /// @return The address of the bond issuer.\n    function bondIssuer() external view returns (IBondIssuer);\n\n    /// @notice Reference to the address that has the ability to pause/unpause operations.\n    /// @return The address of the keeper.\n    function keeper() external view returns (address);\n\n    /// @notice The address of the underlying rebasing ERC-20 collateral token backing the tranches.\n    /// @return Address of the underlying collateral token.\n    function underlying() external view returns (IERC20Upgradeable);\n\n    /// @return Address of perp's rollover vault.\n    function vault() external view returns (IRolloverVault);\n\n    /// @notice The parent bond whose tranches are currently accepted to mint perp tokens.\n    /// @return Address of the deposit bond.\n    function getDepositBond() external returns (IBondController);\n\n    /// @notice The tranche token contract currently accepted to mint perp tokens.\n    /// @return Address of the deposit tranche ERC-20 token.\n    function getDepositTranche() external returns (ITranche);\n\n    /// @return The tranche ratio of the current deposit tranche.\n    function getDepositTrancheRatio() external returns (uint256);\n\n    /// @notice The policy contract with the fee computation logic for the perp and vault systems.\n    /// @return Address of the policy contract.\n    function feePolicy() external view returns (IFeePolicy);\n\n    /// @notice Total count of tokens held in the reserve.\n    /// @return The reserve token count.\n    function getReserveCount() external returns (uint256);\n\n    /// @notice The token address from the reserve list by index.\n    /// @param index The index of a token.\n    /// @return The reserve token address.\n    function getReserveAt(uint256 index) external returns (IERC20Upgradeable);\n\n    /// @notice Checks if the given token is part of the reserve.\n    /// @param token The address of a token to check.\n    /// @return If the token is part of the reserve.\n    function inReserve(IERC20Upgradeable token) external returns (bool);\n\n    /// @notice Fetches the reserve's token balance.\n    /// @param token The address of the tranche token held by the reserve.\n    /// @return The ERC-20 balance of the reserve token.\n    function getReserveTokenBalance(IERC20Upgradeable token) external returns (uint256);\n\n    /// @notice Calculates the reserve's token value,\n    ///         in a standard denomination as defined by the implementation.\n    /// @param token The address of the tranche token held by the reserve.\n    /// @return The value of the reserve token balance held by the reserve, in a standard denomination.\n    function getReserveTokenValue(IERC20Upgradeable token) external returns (uint256);\n\n    /// @notice Computes the total value of assets currently held in the reserve.\n    /// @return The total value of the perp system, in a standard denomination.\n    function getTVL() external returns (uint256);\n\n    /// @notice Fetches the list of reserve tokens which are up for rollover.\n    /// @return The list of reserve tokens up for rollover.\n    function getReserveTokensUpForRollover() external returns (IERC20Upgradeable[] memory);\n\n    /// @notice Computes the amount of perp tokens minted when `trancheInAmt` `trancheIn` tokens\n    ///         are deposited into the system.\n    /// @param trancheIn The tranche token deposited.\n    /// @param trancheInAmt The amount of tranche tokens deposited.\n    /// @return The amount of perp tokens to be minted.\n    function computeMintAmt(ITranche trancheIn, uint256 trancheInAmt) external returns (uint256);\n\n    /// @notice Computes the amount reserve tokens redeemed when burning given number of perp tokens.\n    /// @param perpAmtBurnt The amount of perp tokens to be burnt.\n    /// @return tokensOut The list of reserve tokens and amounts redeemed.\n    function computeRedemptionAmts(uint256 perpAmtBurnt) external returns (TokenAmount[] memory tokensOut);\n\n    /// @notice Computes the amount reserve tokens that are rolled out for the given number\n    ///         of `trancheIn` tokens rolled in.\n    /// @param trancheIn The tranche token rolled in.\n    /// @param tokenOut The reserve token to be rolled out.\n    /// @param trancheInAmtAvailable The amount of trancheIn tokens rolled in.\n    /// @return r The rollover amounts in various denominations.\n    function computeRolloverAmt(\n        ITranche trancheIn,\n        IERC20Upgradeable tokenOut,\n        uint256 trancheInAmtAvailable\n    ) external returns (RolloverData memory r);\n\n    /// @notice Updates time dependent storage state.\n    function updateState() external;\n}\n"
      },
      "contracts/_interfaces/IRolloverVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { IVault } from \"./IVault.sol\";\nimport { SubscriptionParams } from \"./CommonTypes.sol\";\n\ninterface IRolloverVault is IVault {\n    /// @notice Allows users to swap their underlying tokens for perps held by the vault.\n    /// @param underlyingAmtIn The amount of underlying tokens swapped in.\n    /// @return The amount of perp tokens swapped out.\n    function swapUnderlyingForPerps(uint256 underlyingAmtIn) external returns (uint256);\n\n    /// @notice Allows users to swap their perp tokens for underlying tokens held by the vault.\n    /// @param perpAmtIn The amount of perp tokens swapped in.\n    /// @return The amount of underlying tokens swapped out.\n    function swapPerpsForUnderlying(uint256 perpAmtIn) external returns (uint256);\n\n    /// @notice Computes the amount of perp tokens that are returned when user swaps a given number of underlying tokens.\n    /// @param underlyingAmtIn The number of underlying tokens the user swaps in.\n    /// @return perpAmtOut The number of perp tokens returned to the user.\n    /// @return perpFeeAmtToBurn The amount of perp tokens to be paid to the perp contract as mint fees.\n    /// @return s The pre-swap perp and vault subscription state.\n    function computeUnderlyingToPerpSwapAmt(\n        uint256 underlyingAmtIn\n    ) external returns (uint256, uint256, SubscriptionParams memory);\n\n    /// @notice Computes the amount of underlying tokens that are returned when user swaps a given number of perp tokens.\n    /// @param perpAmtIn The number of perp tokens the user swaps in.\n    /// @return underlyingAmtOut The number of underlying tokens returned to the user.\n    /// @return perpFeeAmtToBurn The amount of perp tokens to be paid to the perp contract as burn fees.\n    /// @return s The pre-swap perp and vault subscription state.\n    function computePerpToUnderlyingSwapAmt(\n        uint256 perpAmtIn\n    ) external returns (uint256, uint256, SubscriptionParams memory);\n}\n"
      },
      "contracts/_interfaces/IVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { TokenAmount } from \"./CommonTypes.sol\";\n\n/*\n *  @title IVault\n *\n *  @notice The standard interface for a generic vault as described by the \"Vault Framework\".\n *          http://thinking.farm/essays/2022-10-05-mechanical-finance/\n *\n *          Users deposit a \"underlying\" asset and mint \"notes\" (or vault shares).\n *          The vault \"deploys\" underlying asset in a rules-based fashion (through a hard-coded strategy).\n *          It \"recovers\" deployed assets once the investment matures.\n *\n *          The vault operates through two external poke functions which off-chain keepers can execute.\n *              1) `deploy`: When executed, the vault \"puts to work\" the underlying assets it holds. The vault\n *                           usually returns other ERC-20 tokens which act as receipts of the deployment.\n *              2) `recover`: When executed, the vault turns in the receipts and retrieves the underlying asset and\n *                            usually collects some yield for this work.\n *\n *          The rules of the deployment and recovery are specific to the vault strategy.\n *\n *          At any time the vault will hold multiple ERC20 tokens, together referred to as the vault's \"assets\".\n *          They can be a combination of the underlying asset and the deployed assets (receipts).\n *\n *          On redemption users burn their \"notes\" to receive a proportional slice of all the vault's assets.\n *\n */\n\ninterface IVault is IERC20Upgradeable {\n    /// @notice Recovers deployed funds and redeploys them.\n    function recoverAndRedeploy() external;\n\n    /// @notice Deploys deposited funds.\n    function deploy() external;\n\n    /// @notice Recovers deployed funds.\n    function recover() external;\n\n    /// @notice Recovers a given deployed asset.\n    /// @param token The ERC-20 token address of the deployed asset.\n    function recover(IERC20Upgradeable token) external;\n\n    /// @notice Deposits the underlying asset from {msg.sender} into the vault and mints notes.\n    /// @param amount The amount tokens to be deposited into the vault.\n    /// @return The amount of notes.\n    function deposit(uint256 amount) external returns (uint256);\n\n    /// @notice Burns notes and sends a proportional share of vault's assets back to {msg.sender}.\n    /// @param notes The amount of notes to be burnt.\n    /// @return The list of asset tokens and amounts redeemed.\n    function redeem(uint256 notes) external returns (TokenAmount[] memory);\n\n    /// @notice Batches the recover and redeem functions.\n    /// @param notes The amount of notes to be burnt.\n    /// @return The list of asset tokens and amounts redeemed.\n    function recoverAndRedeem(uint256 notes) external returns (TokenAmount[] memory);\n\n    /// @return The total value of assets currently held by the vault, denominated in a standard unit of account.\n    function getTVL() external view returns (uint256);\n\n    /// @param token The address of the asset ERC-20 token held by the vault.\n    /// @return The vault's asset token value, denominated in a standard unit of account.\n    function getVaultAssetValue(IERC20Upgradeable token) external view returns (uint256);\n\n    /// @notice The ERC20 token that can be deposited into this vault.\n    function underlying() external view returns (IERC20Upgradeable);\n\n    /// @return Total count of ERC-20 tokens held by the vault.\n    function assetCount() external view returns (uint256);\n\n    /// @param i The index of a token.\n    /// @return The vault's asset token address by index.\n    function assetAt(uint256 i) external view returns (IERC20Upgradeable);\n\n    /// @param token The address of the asset ERC-20 token held by the vault.\n    /// @return The vault's asset token balance.\n    function vaultAssetBalance(IERC20Upgradeable token) external view returns (uint256);\n\n    /// @param token The address of a token to check.\n    /// @return If the given token is held by the vault.\n    function isVaultAsset(IERC20Upgradeable token) external view returns (bool);\n\n    /// @notice Computes the amount of notes minted when given amount of underlying asset tokens\n    ///         are deposited into the system.\n    /// @param amount The amount tokens to be deposited into the vault.\n    /// @return The amount of notes to be minted.\n    function computeMintAmt(uint256 amount) external returns (uint256);\n\n    /// @notice Computes the amount of asset tokens redeemed when burning given number of vault notes.\n    /// @param notes The amount of notes to be burnt.\n    /// @return The list of asset tokens and amounts redeemed.\n    function computeRedemptionAmts(uint256 notes) external returns (TokenAmount[] memory);\n}\n"
      },
      "contracts/_interfaces/ProtocolErrors.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.20;\n\n//-------------------------------------------------------------------------\n// Generic\n\n/// @notice Expected contract call to be triggered by authorized caller.\nerror UnauthorizedCall();\n\n/// @notice Expected transfer out asset to not be a reserve asset.\nerror UnauthorizedTransferOut();\n\n/// @notice Expected contract reference to not be `address(0)`.\nerror UnacceptableReference();\n\n/// @notice Expected interface contract to return a fixed point with a different number of decimals.\nerror UnexpectedDecimals();\n\n/// @notice Expected asset to be a valid reserve/vault asset.\nerror UnexpectedAsset();\n\n/// @notice Expected to mint a non-zero amount of notes.\nerror UnacceptableDeposit();\n\n/// @notice Expected to redeem a non-zero amount of notes.\nerror UnacceptableRedemption();\n\n/// @notice Updated parameters violate defined constraints.\nerror UnacceptableParams();\n\n/// @notice Storage array access out of bounds.\nerror OutOfBounds();\n\n/// @notice Expected the number of reserve assets to be under the limit.\nerror ReserveCountOverLimit();\n\n//-------------------------------------------------------------------------\n// Perp\n\n/// @notice Expected rollover to be acceptable.\nerror UnacceptableRollover();\n\n/// @notice Expected supply to be lower than the defined max supply.\nerror ExceededMaxSupply();\n\n/// @notice Expected the total mint amount per tranche to be lower than the limit.\nerror ExceededMaxMintPerTranche();\n\n//-------------------------------------------------------------------------\n// Vault\n\n/// @notice Expected more underlying token liquidity to perform operation.\nerror InsufficientLiquidity();\n\n/// @notice Expected to swap non-zero assets.\nerror UnacceptableSwap();\n\n/// @notice Expected more assets to be deployed.\nerror InsufficientDeployment();\n\n/// @notice Expected the number of vault assets deployed to be under the limit.\nerror DeployedCountOverLimit();\n\n/// @notice Expected parent bond to have only 2 children tranches.\nerror UnacceptableTrancheLength();\n\n//-------------------------------------------------------------------------\n// Fee Policy\n\n/// @notice Expected perc value to be at most (1 * 10**DECIMALS), i.e) 1.0 or 100%.\nerror InvalidPerc();\n\n/// @notice Expected target subscription ratio to be within defined bounds.\nerror InvalidTargetSRBounds();\n\n/// @notice Expected deviation ratio bounds to be valid.\nerror InvalidDRBounds();\n\n/// @notice Expected sigmoid asymptotes to be within defined bounds.\nerror InvalidSigmoidAsymptotes();\n"
      },
      "contracts/_utils/BondHelpers.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.20;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { IBondController } from \"../_interfaces/buttonwood/IBondController.sol\";\nimport { ITranche } from \"../_interfaces/buttonwood/ITranche.sol\";\nimport { TokenAmount } from \"../_interfaces/CommonTypes.sol\";\nimport { UnacceptableDeposit, UnacceptableTrancheLength } from \"../_interfaces/ProtocolErrors.sol\";\n\nimport { SafeCastUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol\";\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport { BondTranches } from \"./BondTranchesHelpers.sol\";\n\n/**\n *  @title BondHelpers\n *\n *  @notice Library with helper functions for ButtonWood's Bond contract.\n *\n */\nlibrary BondHelpers {\n    using SafeCastUpgradeable for uint256;\n    using MathUpgradeable for uint256;\n\n    // Replicating value used here:\n    // https://github.com/buttonwood-protocol/tranche/blob/main/contracts/BondController.sol\n    uint256 private constant TRANCHE_RATIO_GRANULARITY = 1000;\n\n    /// @notice Given a bond, calculates the time remaining to maturity.\n    /// @param b The address of the bond contract.\n    /// @return The number of seconds before the bond reaches maturity.\n    function secondsToMaturity(IBondController b) internal view returns (uint256) {\n        uint256 maturityDate = b.maturityDate();\n        return maturityDate > block.timestamp ? maturityDate - block.timestamp : 0;\n    }\n\n    /// @notice Given a bond, retrieves all of the bond's tranches.\n    /// @param b The address of the bond contract.\n    /// @return bt The bond's tranche data.\n    function getTranches(IBondController b) internal view returns (BondTranches memory bt) {\n        if (b.trancheCount() != 2) {\n            revert UnacceptableTrancheLength();\n        }\n        (bt.tranches[0], bt.trancheRatios[0]) = b.tranches(0);\n        (bt.tranches[1], bt.trancheRatios[1]) = b.tranches(1);\n    }\n\n    /// @notice Given a bond, returns the tranche at the specified index.\n    /// @param b The address of the bond contract.\n    /// @param i Index of the tranche.\n    /// @return t The tranche address.\n    function trancheAt(IBondController b, uint8 i) internal view returns (ITranche t) {\n        (t, ) = b.tranches(i);\n    }\n\n    /// @notice Given a bond, returns the address of the most senior tranche.\n    /// @param b The address of the bond contract.\n    /// @return t The senior tranche address.\n    function getSeniorTranche(IBondController b) internal view returns (ITranche t) {\n        (t, ) = b.tranches(0);\n    }\n\n    /// @notice Given a bond, returns the tranche ratio of the most senior tranche.\n    /// @param b The address of the bond contract.\n    /// @return r The tranche ratio of the senior most tranche.\n    function getSeniorTrancheRatio(IBondController b) internal view returns (uint256 r) {\n        (, r) = b.tranches(0);\n    }\n\n    /// @notice Helper function to estimate the amount of tranches minted when a given amount of collateral\n    ///         is deposited into the bond.\n    /// @dev This function is used off-chain services (using callStatic) to preview tranches minted.\n    ///      This function assumes that the no fees are withheld for tranching.\n    /// @param b The address of the bond contract.\n    /// @return The tranche data, an array of tranche amounts.\n    function previewDeposit(IBondController b, uint256 collateralAmount) internal view returns (TokenAmount[] memory) {\n        if (b.isMature()) {\n            revert UnacceptableDeposit();\n        }\n\n        BondTranches memory bt = getTranches(b);\n        TokenAmount[] memory tranchesOut = new TokenAmount[](2);\n\n        uint256 totalDebt = b.totalDebt();\n        uint256 collateralBalance = IERC20Upgradeable(b.collateralToken()).balanceOf(address(b));\n\n        uint256 seniorAmt = collateralAmount.mulDiv(bt.trancheRatios[0], TRANCHE_RATIO_GRANULARITY);\n        if (collateralBalance > 0) {\n            seniorAmt = seniorAmt.mulDiv(totalDebt, collateralBalance);\n        }\n        tranchesOut[0] = TokenAmount({ token: bt.tranches[0], amount: seniorAmt });\n\n        uint256 juniorAmt = collateralAmount.mulDiv(bt.trancheRatios[1], TRANCHE_RATIO_GRANULARITY);\n        if (collateralBalance > 0) {\n            juniorAmt = juniorAmt.mulDiv(totalDebt, collateralBalance);\n        }\n        tranchesOut[1] = TokenAmount({ token: bt.tranches[1], amount: juniorAmt });\n\n        return tranchesOut;\n    }\n}\n"
      },
      "contracts/_utils/BondTranchesHelpers.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.20;\n\nimport { ITranche } from \"../_interfaces/buttonwood/ITranche.sol\";\n\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\n\n// @dev We assume that all bonds in the system just have 2 tranches, i.e) one senior and one junior.\nstruct BondTranches {\n    ITranche[2] tranches;\n    uint256[2] trancheRatios;\n}\n\n/**\n *  @title BondTranchesHelpers\n *\n *  @notice Library with helper functions for the bond's retrieved tranche data.\n *\n */\nlibrary BondTranchesHelpers {\n    using MathUpgradeable for uint256;\n\n    /// @notice For a given bond's tranche data and user address, computes the maximum number of each of the bond's tranches\n    ///         the user is able to redeem before the bond's maturity. These tranche amounts necessarily match the bond's tranche ratios.\n    /// @param bt The bond's tranche data.\n    /// @param u The address to check balance for.\n    /// @return An array of tranche token balances.\n    function computeRedeemableTrancheAmounts(\n        BondTranches memory bt,\n        address u\n    ) internal view returns (uint256[] memory) {\n        uint256[] memory trancheBalsAvailable = new uint256[](2);\n        trancheBalsAvailable[0] = bt.tranches[0].balanceOf(u);\n        trancheBalsAvailable[1] = bt.tranches[1].balanceOf(u);\n        return computeRedeemableTrancheAmounts(bt, trancheBalsAvailable);\n    }\n\n    /// @notice For a given bond's tranche data and tranche balances available, computes the maximum number of each of the bond's tranches\n    ///         the user is able to redeem before the bond's maturity.\n    ///         The returned tranche amounts necessarily match the bond's tranche ratios.\n    /// @param bt The bond's tranche data.\n    /// @param trancheBalsAvailable The tranche balance of each bond tranche available to be used for redemption.\n    /// @return An array of tranche token balances.\n    function computeRedeemableTrancheAmounts(\n        BondTranches memory bt,\n        uint256[] memory trancheBalsAvailable\n    ) internal pure returns (uint256[] memory) {\n        uint256[] memory trancheAmtsReq = new uint256[](2);\n\n        // We compute the amount of seniors required using all the juniors\n        trancheAmtsReq[1] = trancheBalsAvailable[1] - (trancheBalsAvailable[1] % bt.trancheRatios[1]);\n        trancheAmtsReq[0] = (trancheAmtsReq[1] * bt.trancheRatios[0]) / bt.trancheRatios[1];\n\n        // If enough seniors aren't available, we compute the amount of juniors required using all the seniors\n        if (trancheAmtsReq[0] > trancheBalsAvailable[0]) {\n            trancheAmtsReq[0] = trancheBalsAvailable[0] - (trancheBalsAvailable[0] % bt.trancheRatios[0]);\n            trancheAmtsReq[1] = (trancheAmtsReq[0] * bt.trancheRatios[1]) / bt.trancheRatios[0];\n        }\n\n        return trancheAmtsReq;\n    }\n}\n"
      },
      "contracts/RouterV2.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.20;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ITranche } from \"./_interfaces/buttonwood/ITranche.sol\";\nimport { IBondController } from \"./_interfaces/buttonwood/IBondController.sol\";\nimport { IPerpetualTranche } from \"./_interfaces/IPerpetualTranche.sol\";\nimport { TokenAmount } from \"./_interfaces/CommonTypes.sol\";\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { SafeCastUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol\";\nimport { BondTranches, BondTranchesHelpers } from \"./_utils/BondTranchesHelpers.sol\";\nimport { BondHelpers } from \"./_utils/BondHelpers.sol\";\n\n/**\n *  @title RouterV2\n *\n *  @notice Contract to dry-run and batch multiple operations.\n *\n */\ncontract RouterV2 {\n    // math\n    using SafeCastUpgradeable for uint256;\n\n    // data handling\n    using BondHelpers for IBondController;\n    using BondTranchesHelpers for BondTranches;\n\n    // ERC20 operations\n    using SafeERC20Upgradeable for IERC20Upgradeable;\n    using SafeERC20Upgradeable for ITranche;\n    using SafeERC20Upgradeable for IPerpetualTranche;\n\n    /// @notice Calculates the amount of tranche tokens minted after depositing into the deposit bond.\n    /// @dev Used by off-chain services to preview a tranche operation.\n    /// @param perp Address of the perp contract.\n    /// @param collateralAmount The amount of collateral the user wants to tranche.\n    /// @return bond The address of the current deposit bond.\n    /// @return trancheAmts The tranche tokens and amounts minted.\n    function previewTranche(\n        IPerpetualTranche perp,\n        uint256 collateralAmount\n    ) external returns (IBondController, TokenAmount[] memory) {\n        IBondController bond = perp.getDepositBond();\n        return (bond, bond.previewDeposit(collateralAmount));\n    }\n\n    /// @notice Tranches the collateral using the current deposit bond and then deposits individual tranches\n    ///         to mint perp tokens. It transfers the perp tokens back to the\n    ///         transaction sender along with any unused tranches and fees.\n    /// @param perp Address of the perp contract.\n    /// @param bond Address of the deposit bond.\n    /// @param collateralAmount The amount of collateral the user wants to tranche.\n    function trancheAndDeposit(IPerpetualTranche perp, IBondController bond, uint256 collateralAmount) external {\n        // If deposit bond does not exist, we first issue it.\n        if (address(bond).code.length <= 0) {\n            perp.updateState();\n        }\n\n        BondTranches memory bt = bond.getTranches();\n        IERC20Upgradeable collateralToken = IERC20Upgradeable(bond.collateralToken());\n\n        // transfers collateral & fees to router\n        collateralToken.safeTransferFrom(msg.sender, address(this), collateralAmount);\n\n        // approves collateral to be tranched\n        _checkAndApproveMax(collateralToken, address(bond), collateralAmount);\n\n        // tranches collateral\n        bond.deposit(collateralAmount);\n\n        // uses senior tranches to mint perps\n        uint256 trancheAmt = bt.tranches[0].balanceOf(address(this));\n        _checkAndApproveMax(bt.tranches[0], address(perp), trancheAmt);\n        perp.deposit(bt.tranches[0], trancheAmt);\n\n        // transfers remaining junior tranches back\n        bt.tranches[1].safeTransfer(msg.sender, bt.tranches[1].balanceOf(address(this)));\n\n        // transfers any remaining collateral tokens back\n        uint256 collateralBalance = collateralToken.balanceOf(address(this));\n        if (collateralBalance > 0) {\n            collateralToken.safeTransfer(msg.sender, collateralBalance);\n        }\n\n        // transfers perp tokens back\n        perp.safeTransfer(msg.sender, perp.balanceOf(address(this)));\n    }\n\n    /// @dev Checks if the spender has sufficient allowance. If not, approves the maximum possible amount.\n    function _checkAndApproveMax(IERC20Upgradeable token, address spender, uint256 amount) private {\n        uint256 allowance = token.allowance(address(this), spender);\n        if (allowance < amount) {\n            token.safeApprove(spender, type(uint256).max);\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 750
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}