creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/TrancheFactory.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.19;\n\n// interfaces\nimport {ITrancheFactory} from \"./interfaces/ITrancheFactory.sol\";\nimport {ITranche} from \"./interfaces/ITranche.sol\";\nimport {IBaseAdapter} from \"./interfaces/IBaseAdapter.sol\";\n// libs\nimport {SafeCast} from \"@openzeppelin/contracts@4.9.3/utils/math/SafeCast.sol\";\nimport {Create2} from \"@openzeppelin/contracts@4.9.3/utils/Create2.sol\";\nimport {MAX_BPS} from \"./Constants.sol\";\nimport {Create2TrancheLib} from \"./Create2TrancheLib.sol\";\n\nimport {Tranche} from \"./Tranche.sol\";\nimport {YieldToken} from \"./YieldToken.sol\";\n\ncontract TrancheFactory is ITrancheFactory {\n    using SafeCast for uint256;\n\n    /// @notice 5% Maximum issuance fee percentage limit in basis point  (10000 = 100%)\n    uint256 internal constant MAX_ISSUANCE_FEE_BPS = 500; // 5%\n\n    /// @dev Keccak256 hash of the Tranche contract creation code\n    /// @dev Used to compute the CREATE2 address of the Tranche contract\n    /// `immutable` is used instead of `constant` for a call to `keccak256()`\n    bytes32 public immutable TRANCHE_CREATION_HASH = keccak256(type(Tranche).creationCode);\n\n    /// @notice management address\n    address public immutable management;\n\n    /// @notice Temporary storage used exclusively during the Tranche contract deployment by the Factory.\n    /// @dev These variables are utilized to initialize the Tranche contract and must be reset post-deployment.\n    TrancheInitArgs internal _tempArgs;\n\n    /// @notice adapter => maturity => principal token\n    mapping(address => mapping(uint256 => address)) public tranches;\n\n    constructor(address _management) {\n        management = _management;\n    }\n\n    /// @inheritdoc ITrancheFactory\n    /// @dev revert if caller is not authorized.\n    ///      revert if tranche instance already exists.\n    ///      revert if maturity is in the past.\n    ///      revert if issueancaeFee is too high.\n    ///\n    /// Internally types shorter than 32bytes are used to save gas. but uint256 is used in function parameters\n    /// because types shorter than 32bytes have some pitfalls.\n    /// @param adapter the adapter to use for this Tranche\n    /// @param maturity uint32 for `maturity` is enough for next 100 years\n    /// @param issuanceFee the issueance fee of this series (in basis points 10_000=100%). can be zero. uint16 internally\n    function deployTranche(address adapter, uint256 maturity, uint256 issuanceFee) external returns (address) {\n        if (msg.sender != management) revert OnlyManagement();\n        if (adapter == address(0)) revert ZeroAddress();\n        if (tranches[adapter][maturity] != address(0)) revert TrancheAlreadyExists();\n        if (maturity <= block.timestamp) revert MaturityInvalid();\n        if (issuanceFee > MAX_ISSUANCE_FEE_BPS) revert IssueanceFeeTooHigh(); // issuanceFee: [0, 5%] inclusive\n\n        // NOTE: computed Tranche address is used before deployed. it is ok if the YT doesn't call the tranche's methods in its constructor\n        address computedAddr = trancheFor(adapter, maturity);\n        YieldToken yt = new YieldToken(\n            computedAddr,\n            IBaseAdapter(adapter).underlying(),\n            IBaseAdapter(adapter).target(),\n            maturity\n        );\n\n        // store temporary variables\n        _tempArgs.adapter = adapter;\n        _tempArgs.maturity = maturity.toUint32();\n        _tempArgs.issuanceFee = issuanceFee.toUint16();\n        _tempArgs.yt = address(yt);\n\n        // deploy PT with CREATE2 using adapter and maturity as salt\n        // receive callback to initialize the tranche\n        Tranche tranche = Create2TrancheLib.deploy(adapter, maturity);\n        if (computedAddr != address(tranche)) revert TrancheAddressMismatch();\n\n        // set back to zero-value for refund\n        delete _tempArgs;\n\n        // store the series\n        tranches[adapter][maturity] = address(tranche);\n        emit TrancheDeployed(maturity, address(tranche), address(yt));\n\n        return address(tranche);\n    }\n\n    /// @inheritdoc ITrancheFactory\n    /// @dev This pattern is used to deploy a contract deterministically with initialization arguments using CREATE2.\n    /// Constructor arguments are fetched from a temporary storage through a callback in the constructor.\n    function args() external view override returns (TrancheInitArgs memory) {\n        return\n            TrancheInitArgs({\n                maturity: _tempArgs.maturity,\n                adapter: _tempArgs.adapter,\n                issuanceFee: _tempArgs.issuanceFee,\n                yt: _tempArgs.yt,\n                management: management\n            });\n    }\n\n    /// @inheritdoc ITrancheFactory\n    function trancheFor(address adapter, uint256 maturity) public view returns (address tranche) {\n        // Optimize salt computation\n        // https://www.rareskills.io/post/gas-optimization#viewer-ed7oh\n        // https://github.com/dragonfly-xyz/useful-solidity-patterns/tree/main/patterns/assembly-tricks-1#hash-two-words\n        bytes32 salt;\n        assembly {\n            mstore(0x00, shr(96, shl(96, adapter))) // note: This is public function, so we should clean the upper 96 bits.\n            mstore(0x20, maturity)\n            salt := keccak256(0x00, 0x40)\n        }\n        tranche = Create2.computeAddress(salt, TRANCHE_CREATION_HASH, address(this));\n    }\n}\n"
      },
      "src/interfaces/ITrancheFactory.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\n/// @title ITrancheFactory\n/// @notice interface for TrancheFactory\ninterface ITrancheFactory {\n    error ZeroAddress();\n    error TrancheAlreadyExists();\n    error MaturityInvalid();\n    error OnlyManagement();\n    error IssueanceFeeTooHigh();\n    error TrancheAddressMismatch();\n\n    event TrancheDeployed(uint256 indexed maturity, address indexed principalToken, address indexed yieldToken);\n\n    /// @notice init args for a tranche\n    /// @param adapter address of the adapter\n    /// @param maturity UNIX timestamp of maturity\n    /// @param issuanceFee fee for issuing PT and YT\n    /// @param yt address of the Yield Token\n    /// @param management management address of the deployed tranche\n    struct TrancheInitArgs {\n        address adapter; // 20 bytes\n        uint32 maturity; // 4 bytes\n        uint16 issuanceFee; // 2 bytes (1th-slot)\n        address yt; // 20 bytes (2nd-slot)\n        address management; // 20 bytes (3rd-slot)\n    }\n\n    /// @notice deploy a new Tranche instance with the given maturity and adapter\n    /// @dev only the management address can call this function\n    /// @param adapter the adapter to use for this series\n    /// @param maturity the maturity of this series (in seconds)\n    /// @param issuanceFee the issueance fee of this series (in basis points 10_000=100%)\n    /// @return the address of the new tranche\n    function deployTranche(address adapter, uint256 maturity, uint256 issuanceFee) external returns (address);\n\n    /// @notice calculate the address of a tranche with CREATE2 using the adapter and maturity as salt\n    function trancheFor(address adapter, uint256 maturity) external view returns (address tranche);\n\n    /// @notice return init args for a tranche\n    function args() external view returns (TrancheInitArgs memory);\n\n    function TRANCHE_CREATION_HASH() external view returns (bytes32);\n}\n"
      },
      "src/interfaces/ITranche.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC5095} from \"./IERC5095.sol\";\n\n/// @notice Tranche interface\n/// @dev Tranche divides a yield-bearing token into two tokens: Principal and Yield tokens\n///      Unspecific types: Simply avoiding dependencies on other interfaces from our interfaces\ninterface ITranche is IERC5095 {\n    /* ==================== ERRORS ===================== */\n\n    error TimestampBeforeMaturity();\n    error TimestampAfterMaturity();\n    error ProtectedToken();\n    error Unauthorized();\n    error OnlyYT();\n    error ReentrancyGuarded();\n    error ZeroAddress();\n    error NoAccruedYield();\n\n    /* ==================== EVENTS ===================== */\n\n    /// @param adapter the address of the adapter\n    /// @param maturity timestamp of maturity (seconds since Unix epoch)\n    /// @param issuanceFee fee for issuing PT and YT\n    event SeriesCreated(address indexed adapter, uint256 indexed maturity, uint256 issuanceFee);\n\n    /// @param from the sender of the underlying token\n    /// @param to the recipient of the PT and YT\n    /// @param underlyingUsed the amount of underlying token used to issue PT and YT\n    /// @param sharesUsed the amount of target token used to issue PT and YT (before deducting issuance fee)\n    event Issue(address indexed from, address indexed to, uint256 underlyingUsed, uint256 sharesUsed);\n\n    /// @param owner the address of the owner of the PT and YT (address that called collect())\n    /// @param shares the amount of Target token collected\n    event Collect(address indexed owner, uint256 shares);\n\n    /// @param owner the address of the owner of the PT and YT\n    /// @param to the recipient of the underlying token redeemed\n    /// @param underlyingRedeemed the amount of underlying token redeemed\n    event RedeemWithYT(address indexed owner, address indexed to, uint256 underlyingRedeemed);\n\n    /* ==================== STRUCTS ===================== */\n\n    /// @notice Series is a struct that contains all the information about a series.\n    /// @param underlying the address of the underlying token\n    /// @param target the address of the target token\n    /// @param yt the address of the Yield Token\n    /// @param adapter the address of the adapter\n    /// @param mscale scale value at maturity\n    /// @param maxscale max scale value from this series' lifetime\n    /// @param issuanceFee fee for issuing PT and YT\n    /// @param maturity timestamp of maturity (seconds since Unix epoch)\n    struct Series {\n        address underlying;\n        address target;\n        address yt;\n        address adapter;\n        uint256 mscale;\n        uint256 maxscale;\n        uint64 issuanceFee;\n        uint64 maturity;\n    }\n\n    /// @notice GlobalScales is a struct that contains scale values that are used in multiple functions throughout the Tranche contract.\n    /// @param mscale scale value at maturity. before maturity and settlement, this value is 0.\n    /// @param maxscale max scale value from this series' lifetime.\n    struct GlobalScales {\n        uint128 mscale;\n        uint128 maxscale;\n    }\n\n    /* ================== MUTATIVE METHODS =================== */\n\n    /// @notice deposit an `underlyingAmount` of underlying token into the yield source, receiving PT and YT.\n    ///         amount of PT and YT issued are the same.\n    /// @param   to the address to receive PT and YT\n    /// @param   underlyingAmount the amount of underlying token to deposit\n    /// @return  principalAmount the amount of PT and YT issued\n    function issue(address to, uint256 underlyingAmount) external returns (uint256 principalAmount);\n\n    /// @notice redeem an `principalAmount` of PT and YT for underlying token.\n    /// @param from the address to burn PT and YT from\n    /// @param to the address to receive underlying token\n    /// @param pyAmount the amount of PT and YT to redeem\n    /// @return underlyingAmount the amount of underlying token redeemed\n    function redeemWithYT(address from, address to, uint256 pyAmount) external returns (uint256 underlyingAmount);\n\n    /// @notice collect interest for `msg.sender` and transfer accrued interest to `msg.sender`\n    /// NOTE: if the maturity has passed, all the YT balance of `msg.sender` is burned.\n    /// @dev anyone can call this function to collect interest for themselves\n    /// @return collected collected interest in Underlying token\n    function collect() external returns (uint256 collected);\n\n    /* ================== PERMISSIONED METHODS =================== */\n\n    /// @notice collect interest from the yield source and distribute it\n    ///         every YT transfer, this function is triggered by the Yield Token contract.\n    ///         only the Yield Token contract can call this function.\n    ///         NOTE: YT is not burned in this function even if the maturity has passed.\n    /// @param from address to transfer the Yield Token from. i.e. the user who collects the interest.\n    /// @param to address to transfer the Yield Token to (MUST NOT be zero address, CAN be the same as `from`)\n    /// @param value amount of Yield Token transferred to `to` (CAN be 0)\n    function updateUnclaimedYield(address from, address to, uint256 value) external;\n\n    /* ================== VIEW METHODS =================== */\n\n    /// @notice get the address of Yield Token associated with this Tranche.\n    function yieldToken() external view returns (address);\n\n    /// @notice get Series struct\n    function getSeries() external view returns (Series memory);\n\n    /// @notice get an accrued yield that can be claimed by `account` (in unis of Target token)\n    /// @dev this is reset to 0 when `account` claims the yield.\n    /// @param account the address to check\n    /// @return accruedInTarget\n    function unclaimedYields(address account) external view returns (uint256 accruedInTarget);\n\n    /// @notice get an accrued yield that can be claimed by `account` (in unis of Underlying token)\n    /// @param account the address to check\n    /// @return accruedInUnderlying accrued yield in underlying token\n    function previewCollect(address account) external view returns (uint256 accruedInUnderlying);\n}\n"
      },
      "src/interfaces/IBaseAdapter.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface IBaseAdapter {\n    /* ============== MUTATIVE METHODS =============== */\n\n    /// @notice update adapter's scale value and return it\n    ///         Underlying decimals: `u`, Target decimals: `t`, Target conversion rate: 10^u / 10^t\n    ///         => Scale = 10^(u-t) * 10^18 = 10^(u-t+18)\n    ///         e.g. WstETH (t=18,u=18) price: 1.2 WETH => scale = 1.2*10^18\n    ///              eUSDC (t=18,u=6) price: 1.01 USDC => scale = 1.01*10^(6-18+18) = 1.01*10^6\n    /// @dev For interest-bearing token, such as cTokens, this is simply the conversion rate\n    /// @dev For other Targets, such as AMM LP shares, specialized logic will be required\n    /// @return scale in units of underlying token\n    function scale() external view returns (uint256);\n\n    /// @notice deposit Underlying in return for Target.\n    function deposit(uint256 underlyingUsed) external returns (uint256 shares);\n\n    /// @notice redeem Target and receive Underlying in return.\n    /// @dev no funds should be left in the contract after this call\n    ///      the caller must transfer Target to this contract before calling this function.\n    /// @param to recipient of Underlying\n    /// @return underlyingWithdrawn amount of Underlying returned\n    /// @return sharesRedeemed amount of Target redeemed\n    function prefundedRedeem(address to) external returns (uint256 underlyingWithdrawn, uint256 sharesRedeemed);\n\n    /* =============== VIEW METHODS ================ */\n\n    /// @notice return Underlying token address (eg USDC, DAI)\n    /// @return Underlying address\n    function underlying() external view returns (address);\n\n    /// @notice return yield-bearing token address (eg cUSDC, wstETH, AMM LP shares)\n    /// @return Target address (yield-bearing token)\n    function target() external view returns (address);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.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 SafeCast {\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"
      },
      "lib/openzeppelin-contracts/contracts/utils/Create2.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Create2.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n    /**\n     * @dev Deploys a contract using `CREATE2`. The address where the contract\n     * will be deployed can be known in advance via {computeAddress}.\n     *\n     * The bytecode for a contract can be obtained from Solidity with\n     * `type(contractName).creationCode`.\n     *\n     * Requirements:\n     *\n     * - `bytecode` must not be empty.\n     * - `salt` must have not been used for `bytecode` already.\n     * - the factory must have a balance of at least `amount`.\n     * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n     */\n    function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\n        require(address(this).balance >= amount, \"Create2: insufficient balance\");\n        require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n        /// @solidity memory-safe-assembly\n        assembly {\n            addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n        }\n        require(addr != address(0), \"Create2: Failed on deploy\");\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n     * `bytecodeHash` or `salt` will result in a new destination address.\n     */\n    function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n        return computeAddress(salt, bytecodeHash, address(this));\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n     * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n     */\n    function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40) // Get free memory pointer\n\n            // |                   | ↓ ptr ...  ↓ ptr + 0x0B (start) ...  ↓ ptr + 0x20 ...  ↓ ptr + 0x40 ...   |\n            // |-------------------|---------------------------------------------------------------------------|\n            // | bytecodeHash      |                                                        CCCCCCCCCCCCC...CC |\n            // | salt              |                                      BBBBBBBBBBBBB...BB                   |\n            // | deployer          | 000000...0000AAAAAAAAAAAAAAAAAAA...AA                                     |\n            // | 0xFF              |            FF                                                             |\n            // |-------------------|---------------------------------------------------------------------------|\n            // | memory            | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |\n            // | keccak(start, 85) |            ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |\n\n            mstore(add(ptr, 0x40), bytecodeHash)\n            mstore(add(ptr, 0x20), salt)\n            mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes\n            let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff\n            mstore8(start, 0xff)\n            addr := keccak256(start, 85)\n        }\n    }\n}\n"
      },
      "src/Constants.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.19;\n\nuint256 constant WAD = 1e18;\n\n// @notice 100% in basis points. 10_000 = 100%s\nuint256 constant MAX_BPS = 10_000;\n\n/* =============== ADDRESSES ================ */\n\n// @notice WETH address on mainnet\naddress constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n\n// @notice stETH address on mainnet\naddress constant STETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84;\n\n// @notice wstETH address on mainnet\naddress constant WSTETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;\n\n// @notice WithdrawalQueueERC721 of LIDO address on mainnet\naddress constant LIDO_WITHDRAWAL_QUEUE = 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1;\n\n// @notice rETH address on mainnet\naddress constant RETH = 0xae78736Cd615f374D3085123A210448E74Fc6393;\n\n// @notice eETH address on mainnet\naddress constant EETH = 0x35fA164735182de50811E8e2E824cFb9B6118ac2;\n\n// @notice cETH address on mainnet\naddress constant CETH = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5;\n\n// @notice CDAI address on mainnet\naddress constant CDAI = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643;\n\n// @notice DAI address on mainnet\naddress constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n\n// @notice COMPTROLLER address on mainnet\naddress constant COMPTROLLER = 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B;\n\n// @notice COMP address on mainnet\naddress constant COMP = 0xc00e94Cb662C3520282E6f5717214004A7f26888;\n\n// @notice AWETH address on mainnet\naddress constant AWETH = 0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8;\n\n// @notice LendingAAVEV3_POOL_ADDRESSES_PROVIDER address on mainnet\naddress constant AAVEV3_POOL_ADDRESSES_PROVIDER = 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e;\n\n// @notice ma3WETH ERC 4626 Vault address on mainnet\naddress constant MA3WETH = 0x39Dd7790e75C6F663731f7E1FdC0f35007D3879b;\n\n// @notice Morpho Aave v3 optimizer contract address on mainnet\naddress constant MORPHO_AAVE_V3 = 0x33333aea097c193e66081E930c33020272b33333;\n\n// @notice MORPHO token address on mainnet\naddress constant MORPHO = 0x9994E35Db50125E0DF82e4c2dde62496CE330999;\n\n// @notice Frax Ether address on mainnet\naddress constant FRXETH = 0x5E8422345238F34275888049021821E8E08CAa1f;\n\n// @notice Staked Frax Ether address on mainnet\naddress constant STAKED_FRXETH = 0xac3E018457B222d93114458476f3E3416Abbe38F;\n\n// @notice EtherFi LiquidityPool\naddress constant ETHERFI_LP = 0x308861A430be4cce5502d0A12724771Fc6DaF216;\n\n// @notice EtherFi WETH\naddress constant ETHERFI_WEETH = 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee;\n\n// @notice EtherFi WithdrawRequestNFT\naddress constant ETHERFI_WITHDRAW_REQUEST = 0x7d5706f6ef3F89B3951E23e557CDFBC3239D4E2c;\n\n// @notice BedRock uniETH address on mainnet\naddress constant UNIETH = 0xF1376bceF0f78459C0Ed0ba5ddce976F1ddF51F4;\n\n// @notice BedRock Staking address on mainnet\naddress constant BEDROCK_STAKING = 0x4beFa2aA9c305238AA3E0b5D17eB20C045269E9d;\n"
      },
      "src/Create2TrancheLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.19;\n\nimport {Tranche} from \"./Tranche.sol\";\n\n/// @notice Library for deploying Tranche contracts using CREATE2\n/// @dev External library functions are used to downsize the TrancheFactory contract\nlibrary Create2TrancheLib {\n    function deploy(address adapter, uint256 maturity) external returns (Tranche) {\n        bytes32 salt;\n        assembly {\n            mstore(0x00, adapter) // note: ABI encoder v2 verifies the upper 96 bits are clean.\n            mstore(0x20, maturity)\n            salt := keccak256(0x00, 0x40)\n        }\n        return new Tranche{salt: salt}();\n    }\n}\n"
      },
      "src/Tranche.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.19;\n\n// interfaces\nimport {IERC20} from \"@openzeppelin/contracts@4.9.3/token/ERC20/IERC20.sol\";\nimport {IERC5095} from \"./interfaces/IERC5095.sol\";\nimport {ITranche} from \"./interfaces/ITranche.sol\";\nimport {IYieldToken} from \"./interfaces/IYieldToken.sol\";\nimport {ITrancheFactory} from \"./interfaces/ITrancheFactory.sol\";\nimport {IBaseAdapter} from \"./interfaces/IBaseAdapter.sol\";\n// libs\nimport {Math} from \"@openzeppelin/contracts@4.9.3/utils/math/Math.sol\";\nimport {FixedPointMathLib} from \"./utils/FixedPointMathLib.sol\";\nimport {SafeCast} from \"@openzeppelin/contracts@4.9.3/utils/math/SafeCast.sol\";\nimport {SafeERC20Namer} from \"./utils/SafeERC20Namer.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts@4.9.3/token/ERC20/utils/SafeERC20.sol\";\nimport {MAX_BPS} from \"./Constants.sol\";\n// inheriting\nimport {ERC20Permit, ERC20} from \"@openzeppelin/contracts@4.9.3/token/ERC20/extensions/ERC20Permit.sol\";\nimport {Pausable} from \"@openzeppelin/contracts@4.9.3/security/Pausable.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts@4.9.3/security/ReentrancyGuard.sol\";\nimport {BaseToken} from \"./BaseToken.sol\";\n\n/// @title Tranche\n/// @author Napier Labs\n/// @author 0xbakuchi\n/// @notice Tranche divides a yield-bearing token into two tokens: principal token and yield token.\n/// This contract itself is a principal token.\n/// Users can interact with this contract to issue, redeem tokens, and gather yield.\n/// Both the Principal and Yield tokens share the same decimal notation as the underlying token.\n/// Math:\n/// - Yield Stripping Math paper: https://github.com/Napier-Lab/napier-v1/blob/main/assets/Yield_Stripping_Math__1_.pdf\n/// - Hackmd: https://hackmd.io/W2mPhP7YRjGxqnAc93omLg?both\n/// PT/YT and Target token conversion is defined as:\n/// P = T * scale / 1e18\n///   = T * price * 10^(18 + uDecimals - tDecimals) / 1e18\n/// Where P is amount of PT and T is amount of Target.\n/// @dev Supported Tokens:\n/// - Underlying token can be rebased token.\n/// - Underlying must not be ERC777 token.\n/// - Target token can not be rebased token.\ncontract Tranche is BaseToken, ReentrancyGuard, Pausable, ITranche {\n    using SafeERC20 for IERC20;\n    using FixedPointMathLib for uint256;\n    using SafeCast for uint256;\n\n    uint8 internal immutable uDecimals;\n\n    /// @notice Represents the underlying token where users deposit (e.g. DAI)\n    IERC20 internal immutable _underlying;\n\n    /// @notice Represents the yield-bearing token (e.g. cDAI)\n    IERC20 internal immutable _target;\n\n    /// @notice Represents the Yield token that represents the right to claim the yield\n    IYieldToken internal immutable _yt;\n\n    /// @notice An adapter that interacts with the yield source (e.g. Compound)\n    IBaseAdapter public immutable adapter;\n\n    /// @notice Address of the management account\n    address public immutable management;\n\n    // Principal token Parameters\n\n    /// @inheritdoc IERC5095\n    /// @notice The timestamp of maturity in unix seconds\n    uint256 public immutable override(BaseToken, IERC5095) maturity;\n\n    /// @notice The fee for issuing new tokens (10000 = 100%)\n    uint256 internal immutable issuanceFeeBps;\n\n    //////////////////////////////////////////////////\n    // State Variables\n    //////////////////////////////////////////////////\n\n    /// @notice Variables tracking the yield-bearing token's scales\n    /// @dev This is used to calculate the claimable yield and is updated on every issue, collect, and redeemYT action.\n    ///  - `mscale` represents the scale of the yield-bearing token at or after maturity,\n    /// it is set only at the time of users redeeming, redeemingYT and collecting at/after maturity.\n    ///  - `maxscale` represents the maximum scale of the yield-bearing token since the Tranche's creation till now.\n    GlobalScales internal gscales;\n\n    /// @dev The address that receives the issuance fees. This address can be changed by the `management`.\n    address public feeRecipient;\n\n    /// @notice The total amount of fees collected by the protocol since the last claim.\n    /// @dev Every time a user issues PT and YT, the issuance fee is collected and added to this variable.\n    uint256 public protocolFees;\n\n    /// @notice Keeps track of the scale of the target token at the last user action.\n    /// @dev It is used for calculating the yield that can be claimed. It gets updated on every user action.\n    /// user -> lscale (last scale)\n    /// See \"Yield Stripping Math\" for more details.\n    mapping(address => uint256) public lscales;\n\n    /// @notice Keeps track of the yield not claimed by each user in units of the target token.\n    /// @dev This value is reset to 0 on every issue, collect and redeemYT action. Every YT transfer also increases this value.\n    mapping(address => uint256) public unclaimedYields;\n\n    /* ================== MODIFIERS =================== */\n\n    /// @notice Revert if timestamp is before maturity\n    modifier expired() {\n        if (block.timestamp < maturity) revert TimestampBeforeMaturity();\n        _;\n    }\n\n    /// @notice Revert if timestamp is at or after maturity\n    modifier notExpired() {\n        if (block.timestamp >= maturity) revert TimestampAfterMaturity();\n        _;\n    }\n\n    /// @notice Revert if reentrancy guard is already set to `entered`\n    modifier notEntered() {\n        if (_reentrancyGuardEntered()) revert ReentrancyGuarded();\n        _;\n    }\n\n    /// @notice Revert if msg sender is not management address\n    modifier onlyManagement() {\n        if (msg.sender != management) revert Unauthorized();\n        _;\n    }\n\n    /// @dev Assume Tranche is deployed from a factory.\n    /// Doesn't take constructor arguments directly so that CREATE2 address is independent of the constructor arguments.\n    /// The arguments are fetched through a callback to the factory.\n    /// @custom:param _args The arguments for the Tranche contract.\n    ///\n    /// The constructor is `payable` to remove msg.value check and reduce about 198 gas cost at deployment time.\n    /// This is acceptable because the factory contract doesn't deploy Tranche with ETH.\n    constructor() payable ERC20(\"Napier Principal Token\", \"ePT\") ERC20Permit(\"Napier Principal Token\") {\n        // Retrieve constructor arguments from the factory\n        ITrancheFactory.TrancheInitArgs memory args = ITrancheFactory(msg.sender).args();\n        address underlying_ = IBaseAdapter(args.adapter).underlying();\n        address target_ = IBaseAdapter(args.adapter).target();\n\n        // Initialize immutable and state variables\n        feeRecipient = args.management;\n        management = args.management;\n\n        _underlying = IERC20(underlying_);\n        _target = IERC20(target_);\n        _yt = IYieldToken(args.yt);\n        adapter = IBaseAdapter(args.adapter);\n        issuanceFeeBps = args.issuanceFee;\n        maturity = args.maturity;\n        uDecimals = ERC20(underlying_).decimals();\n        // Set maxscale to the current scale\n        gscales.maxscale = IBaseAdapter(args.adapter).scale().toUint128();\n\n        IERC20(underlying_).forceApprove(args.adapter, type(uint256).max);\n\n        emit SeriesCreated(args.adapter, args.maturity, args.issuanceFee);\n    }\n\n    /* ================== MUTATIVE METHODS =================== */\n\n    /// @inheritdoc ITranche\n    /// @notice This function issues Principal Token (PT) and Yield Token (YT) to `to` in exchange for `underlyingAmount` of underlying token.\n    /// Issuance Fee is charged on the amount of underlying token used to issue PT and YT.\n    /// If `to` has accrued some yield, it will be added to the user's unclaimed yield and can be claimed later.\n    /// @dev The function will be reverted if the maturity has passed.\n    /// @param to The recipient of PT and YT\n    /// @param underlyingAmount The amount of underlying token to be deposited. (in units of underlying token)\n    /// @return issued The amount of PT and YT minted\n    function issue(\n        address to,\n        uint256 underlyingAmount\n    ) external nonReentrant whenNotPaused notExpired returns (uint256 issued) {\n        uint256 _lscale = lscales[to];\n        uint256 _maxscale = gscales.maxscale;\n\n        // NOTE: Updating mscale/maxscale in the cache before the issue to determine the accrued yield.\n        uint256 cscale = adapter.scale();\n\n        if (cscale > _maxscale) {\n            // If the current scale is greater than the maxscale, update scales\n            _maxscale = cscale;\n            gscales.maxscale = cscale.toUint128();\n        }\n\n        // Deduct the issuance fee from the amount of underlying token deposited by the user\n        // Fee should be rounded up towards the protocol (against the user) so that issued principal is rounded down\n        // ```\n        // fee = u * feeBps\n        // shares = (u - fee) / s\n        // ptIssued = shares * S\n        // ```\n        // where u = underlyingAmount, s = current scale and S = maxscale\n        uint256 fee = underlyingAmount.mulDivUp(issuanceFeeBps, MAX_BPS);\n\n        // Updating user's last scale to the latest maxscale\n        lscales[to] = _maxscale;\n        protocolFees += fee;\n\n        // If recipient has unclaimed interest, add it to the user's unclaimed yield.\n        // Reminder: lscale is the last scale when the YT balance of the user was updated.\n        if (_lscale != 0) {\n            uint256 yBal = _yt.balanceOf(to);\n            unclaimedYields[to] += _computeAccruedInterestInTarget(_maxscale, _lscale, yBal);\n        }\n\n        _underlying.safeTransferFrom(msg.sender, address(this), underlyingAmount);\n        uint256 shares = adapter.deposit(underlyingAmount - fee);\n\n        // Compute the amount of PT and YT to be minted\n        // See above for the formula\n        issued = shares.mulWadDown(_maxscale);\n\n        // Mint PT and YT to user\n        _mint(to, issued);\n        _yt.mint(to, issued);\n\n        emit Issue(msg.sender, to, issued, shares);\n    }\n\n    /// @inheritdoc ITranche\n    /// @notice Withdraws underlying tokens from the caller in exchange for `amount` of PT and YT.\n    /// 1 PT + 1 YT = 1 Target token (e.g. 1 wstETH). This equation is always true\n    /// because PT represents the principal amount of the Target token and YT represents the yield of the Target token.\n    /// Basically, anyone can burn `x` PT and `x` YT to withdraw `x` Target tokens anytime.\n    ///\n    /// Withdrawn amount will be the sum of the following:\n    /// - amount derived from PT + YT burn\n    /// - amount of unclaimed yield\n    /// - amount of accrued yield from the last time when the YT balance was updated to now\n    /// @notice If the caller is not `from`, `from` must have approved the caller to spend `pyAmount` for PT and YT prior to calling this function.\n    /// @dev Reverts if the caller does not have enough PT and YT.\n    /// @param from The owner of PT and YT.\n    /// @param to The recipient of the redeemed underlying tokens.\n    /// @param pyAmount The amount of principal token (and yield token) to redeem in units of underlying tokens.\n    /// @return (uint256) The amount of underlying tokens redeemed.\n    function redeemWithYT(address from, address to, uint256 pyAmount) external nonReentrant returns (uint256) {\n        uint256 _lscale = lscales[from];\n        uint256 accruedInTarget = unclaimedYields[from];\n\n        // Calculate the accrued interest in Target token\n        // The lscale should not be 0 because the user should have some YT balance\n        if (_lscale == 0) revert NoAccruedYield();\n\n        GlobalScales memory _gscales = gscales;\n        _updateGlobalScalesCache(_gscales);\n\n        uint256 ytBal = _yt.balanceOf(from);\n        // Compute the accrued yield from the time when the YT balance is updated last to now\n        // The accrued yield in units of target is computed as:\n        // Formula: yield = ytBalance * (1/lscale - 1/maxscale)\n        // Sum up the accrued yield, plus the unclaimed yield from the last time to now\n        accruedInTarget += _computeAccruedInterestInTarget(\n            _gscales.maxscale,\n            _lscale,\n            // Use yt balance instead of `pyAmount`\n            // because we'll update the user's lscale to the current maxscale after this line\n            // regardless of whether the user redeems all of their yt or not.\n            // Otherwise, the user will lose some accrued yield from the last time to now.\n            ytBal\n        );\n        // Compute shares equivalent to the amount of principal token to redeem\n        uint256 sharesRedeemed = pyAmount.divWadDown(_gscales.maxscale);\n\n        // Update the local scale and accrued yield of `from`\n        lscales[from] = _gscales.maxscale;\n        gscales = _gscales;\n        uint256 accruedProportional = (accruedInTarget * pyAmount) / ytBal;\n        unclaimedYields[from] = accruedInTarget - accruedProportional;\n\n        // Burn PT and YT tokens from `from`\n        _burnFrom(from, pyAmount);\n        _yt.burnFrom(from, msg.sender, pyAmount);\n\n        // Withdraw underlying tokens from the adapter and transfer them to the user\n        _target.safeTransfer(address(adapter), sharesRedeemed + accruedProportional);\n        (uint256 amountWithdrawn, ) = adapter.prefundedRedeem(to);\n\n        emit RedeemWithYT(from, to, amountWithdrawn);\n        return amountWithdrawn;\n    }\n\n    /// @inheritdoc IERC5095\n    /// @notice If the sender is not `from`, it must have approval from `from` to redeem `principalAmount` PT.\n    /// Redeems `principalAmount` PT from `from` and transfers underlying tokens to `to`.\n    /// @dev Reverts if maturity has not passed.\n    /// @param principalAmount The amount of principal tokens to redeem in units of underlying tokens.\n    /// @param to The recipient of the redeemed underlying tokens.\n    /// @param from The owner of the PT.\n    /// @return (uint256) The amount of underlying tokens redeemed.\n    function redeem(\n        uint256 principalAmount,\n        address to,\n        address from\n    ) external override nonReentrant expired returns (uint256) {\n        GlobalScales memory _gscales = gscales;\n        _updateGlobalScalesCache(_gscales);\n\n        // Compute the shares to be redeemed\n        uint256 shares = _computeSharesRedeemed(_gscales, principalAmount);\n\n        gscales = _gscales;\n        // Burn PT tokens from `from`\n        _burnFrom(from, principalAmount);\n        // Withdraw underlying tokens from the adapter and transfer them to `to`\n        _target.safeTransfer(address(adapter), shares);\n        (uint256 underlyingWithdrawn, ) = adapter.prefundedRedeem(to);\n\n        emit Redeem(from, to, underlyingWithdrawn);\n        return underlyingWithdrawn;\n    }\n\n    /// @inheritdoc IERC5095\n    /// @notice If the sender is not `from`, it must have approval from `from` to redeem an equivalent amount of principal tokens.\n    /// Redeems PT equivalent to `underlyingAmount` underlying tokens from `from` and transfers underlying tokens to `to`.\n    /// @notice Note: The function doesn't comply with EIP-5095. `to` may receive an amount of underlying tokens not exactly equal to the input parameter `underlyingAmount`\n    /// @dev Reverts if maturity has not passed.\n    /// @param underlyingAmount The amount of underlying tokens to redeem in units of underlying tokens.\n    /// @param to The recipient of the redeemed underlying tokens.\n    /// @param from The owner of the PT.\n    /// @return (uint256) The amount of principal tokens redeemed.\n    function withdraw(\n        uint256 underlyingAmount,\n        address to,\n        address from\n    ) external override nonReentrant expired returns (uint256) {\n        GlobalScales memory _gscales = gscales;\n        uint256 cscale = _updateGlobalScalesCache(_gscales);\n\n        // Compute the shares to be redeemed\n        uint256 sharesRedeem = underlyingAmount.divWadDown(cscale);\n        uint256 principalAmount = _computePrincipalTokenRedeemed(_gscales, sharesRedeem);\n\n        // Update the global scales\n        gscales = _gscales;\n        // Burn PT tokens from `from`\n        _burnFrom(from, principalAmount);\n        // Withdraw underlying tokens from the adapter and transfer them to `to`\n        _target.safeTransfer(address(adapter), sharesRedeem);\n        (uint256 underlyingWithdrawn, ) = adapter.prefundedRedeem(to);\n\n        emit Redeem(from, to, underlyingWithdrawn);\n        return principalAmount;\n    }\n\n    /// @notice Before transferring YT, update the accrued yield for the sender and receiver.\n    /// NOTE: Every YT transfer will trigger this function to track accrued yield for each user.\n    /// @dev This function is only callable by the Yield Token contract when the user transfers YT to another user.\n    /// NOTE: YT is not burned in this function even if the maturity has passed.\n    /// @param from The address to transfer the Yield Token from.\n    /// @param to The address to transfer the Yield Token to (CAN be the same as `from`).\n    /// NOTE: `from` and `to` SHOULD NOT be zero addresses.\n    /// @param value The amount of Yield Token transferred to `to` (CAN be 0).\n    function updateUnclaimedYield(address from, address to, uint256 value) external nonReentrant whenNotPaused {\n        if (msg.sender != address(_yt)) revert OnlyYT();\n        if (from == address(0) || to == address(0)) revert ZeroAddress();\n        if (value == 0) return;\n\n        GlobalScales memory _gscales = gscales;\n        uint256 _lscaleFrom = lscales[from];\n\n        // If the lscale is 0, it means the user have never hold any YT before\n        // because the lscale is always set to maxscale when the YT is transferrred or minted.\n        // This doesn't mean current YT balance is 0 because the user could have transferred all YT out or burned YT.\n        // Thus there is no accrued interest for the user.\n        if (_lscaleFrom == 0) revert NoAccruedYield();\n\n        _updateGlobalScalesCache(_gscales);\n\n        // Calculate the accrued interest in Target token for `from`\n        unclaimedYields[from] += _computeAccruedInterestInTarget(_gscales.maxscale, _lscaleFrom, _yt.balanceOf(from));\n        lscales[from] = _gscales.maxscale;\n\n        // Calculate the accrued interest in Target token for `to`. `from` and `to` can be equal.\n        uint256 _lscaleReceiver = lscales[to];\n        if (_lscaleReceiver != 0) {\n            unclaimedYields[to] +=\n                _computeAccruedInterestInTarget(_gscales.maxscale, _lscaleReceiver, _yt.balanceOf(to)); // prettier-ignore\n        }\n        lscales[to] = _gscales.maxscale;\n        // update global scales\n        gscales = _gscales;\n    }\n\n    /// @notice Collects yield for `msg.sender` and converts it to underlying token and transfers it to `msg.sender`.\n    /// NOTE: If the maturity has passed, YT will be burned.\n    /// The withdrwan amount of underlying token is the sum of the following:\n    /// - Amount of unclaimed yield\n    /// - Amount of accrued yield from the time when the YT balance was updated to now\n    /// @dev Anyone can call this function to collect yield for themselves.\n    /// @return The collected yield in underlying token.\n    function collect() public nonReentrant whenNotPaused returns (uint256) {\n        uint256 _lscale = lscales[msg.sender];\n        uint256 accruedInTarget = unclaimedYields[msg.sender];\n\n        if (_lscale == 0) revert NoAccruedYield();\n\n        GlobalScales memory _gscales = gscales;\n        _updateGlobalScalesCache(_gscales);\n\n        uint256 yBal = _yt.balanceOf(msg.sender);\n        accruedInTarget += _computeAccruedInterestInTarget(_gscales.maxscale, _lscale, yBal);\n        lscales[msg.sender] = _gscales.maxscale;\n        delete unclaimedYields[msg.sender];\n        gscales = _gscales;\n\n        // If matured, burn all the YT balance of the user\n        if (block.timestamp >= maturity) _yt.burn(msg.sender, yBal);\n\n        // Convert the accrued yield in Target token to underlying token and transfer it to the `msg.sender`\n        // Target token may revert if zero-amount transfer is not allowed.\n        _target.safeTransfer(address(adapter), accruedInTarget);\n        (uint256 accrued, ) = adapter.prefundedRedeem(msg.sender);\n        emit Collect(msg.sender, accruedInTarget);\n        return accrued;\n    }\n\n    function claimProtocolFees() external onlyManagement {\n        uint256 fees = protocolFees - 1;\n        protocolFees = 1;\n        _underlying.safeTransfer(feeRecipient, fees);\n    }\n\n    /* ================== VIEW METHODS =================== */\n\n    /// @inheritdoc ITranche\n    /// @dev This function is useful for off-chain services to get the accrued yield of a user.\n    /// @dev This function must not revert in any case.\n    function previewCollect(address account) external view returns (uint256) {\n        uint256 _lscale = lscales[account];\n        uint256 accruedInTarget = unclaimedYields[account];\n\n        // If the lscale is 0, it means the user have never hold any YT before\n        if (_lscale == 0) return 0;\n\n        GlobalScales memory _gscales = gscales;\n        uint256 cscale = _updateGlobalScalesCache(_gscales);\n\n        // At this point, the scales cache is up to date.\n        // Calculate the accrued yield in Target token for `account`\n\n        uint256 yBal = _yt.balanceOf(account);\n        accruedInTarget += _computeAccruedInterestInTarget(_gscales.maxscale, _lscale, yBal);\n\n        // Convert the accrued yield to underlying token\n        return accruedInTarget.mulWadDown(cscale);\n    }\n\n    /// @inheritdoc IERC5095\n    function maxRedeem(address owner) external view override notEntered returns (uint256) {\n        // Before maturity, PT can't be redeemed. Return 0.\n        if (block.timestamp < maturity) return 0;\n        return balanceOf(owner);\n    }\n\n    /// @inheritdoc IERC5095\n    function maxWithdraw(address owner) external view override returns (uint256 maxUnderlyingAmount) {\n        if (block.timestamp < maturity) return 0;\n        return convertToUnderlying(balanceOf(owner));\n    }\n\n    /// @inheritdoc IERC5095\n    function previewRedeem(uint256 principalAmount) external view override returns (uint256 underlyingAmount) {\n        if (block.timestamp < maturity) return 0;\n        return convertToUnderlying(principalAmount);\n    }\n\n    /// @inheritdoc IERC5095\n    function previewWithdraw(uint256 underlyingAmount) external view override returns (uint256 principalAmount) {\n        if (block.timestamp < maturity) return 0;\n        return convertToPrincipal(underlyingAmount);\n    }\n\n    /// @inheritdoc IERC5095\n    /// @dev Before maturity, the amount of underlying returned is as if the PTs would be at maturity.\n    function convertToUnderlying(\n        uint256 principalAmount\n    ) public view override notEntered returns (uint256 underlyingAmount) {\n        GlobalScales memory _gscales = gscales; // Load gscales into memory\n        uint128 cscale = adapter.scale().toUint128();\n        if (_gscales.mscale == 0) {\n            // Simulate the settlement as if it is settled now\n            _gscales.mscale = cscale;\n            if (cscale > _gscales.maxscale) {\n                _gscales.maxscale = cscale;\n            }\n        }\n        uint256 shares = _computeSharesRedeemed(_gscales, principalAmount);\n\n        return shares.mulWadDown(cscale);\n    }\n\n    /// @inheritdoc IERC5095\n    /// @dev Before maturity, the amount of underlying returned is as if the PTs would be at maturity.\n    function convertToPrincipal(uint256 underlyingAmount) public view override notEntered returns (uint256) {\n        GlobalScales memory _gscales = gscales; // Load gscales into memory\n        uint128 cscale = adapter.scale().toUint128();\n        if (_gscales.mscale == 0) {\n            // Simulate the settlement as if it is settled now\n            _gscales.mscale = cscale;\n            if (cscale > _gscales.maxscale) {\n                _gscales.maxscale = cscale;\n            }\n        }\n        return _computePrincipalTokenRedeemed(_gscales, underlyingAmount.divWadDown(cscale));\n    }\n\n    /* ================== METADATA =================== */\n\n    /// @inheritdoc ITranche\n    /// @dev We return the address type instead of IERC20 to avoid additional dependencies for integrators.\n    function yieldToken() external view returns (address) {\n        return address(_yt);\n    }\n\n    /// @inheritdoc IERC5095\n    /// @dev We return the address type instead of IERC20 to avoid additional dependencies for integrators.\n    function underlying() external view returns (address) {\n        return address(_underlying);\n    }\n\n    /// @inheritdoc BaseToken\n    /// @dev We return the address type instead of IERC20 to avoid additional dependencies for integrators.\n    function target() external view override returns (address) {\n        return address(_target);\n    }\n\n    /// @inheritdoc ERC20\n    function name() public view override returns (string memory) {\n        string memory tokenName = SafeERC20Namer.tokenName(address(_target));\n        return string.concat(\"Napier Principal Token \", tokenName, \"@\", _toDateString(maturity));\n    }\n\n    /// @inheritdoc ERC20\n    function symbol() public view override returns (string memory) {\n        string memory tokenSymbol = SafeERC20Namer.tokenSymbol(address(_target));\n        return string.concat(\"PT-\", tokenSymbol, \"@\", _toDateString(maturity));\n    }\n\n    /// @inheritdoc ERC20\n    function decimals() public view override returns (uint8) {\n        return uDecimals;\n    }\n\n    /// @notice get the global scales\n    function getGlobalScales() external view notEntered returns (GlobalScales memory) {\n        return gscales;\n    }\n\n    /// @inheritdoc ITranche\n    /// @notice This function is useful for off-chain services to get the series information.\n    function getSeries() external view notEntered returns (Series memory) {\n        GlobalScales memory _gscales = gscales;\n        return\n            Series({\n                underlying: address(_underlying),\n                target: address(_target),\n                yt: address(_yt),\n                adapter: address(adapter),\n                mscale: _gscales.mscale,\n                maxscale: _gscales.maxscale,\n                issuanceFee: issuanceFeeBps.toUint64(),\n                maturity: maturity.toUint64()\n            });\n    }\n\n    /* ================== PERMISSIONED METHODS =================== */\n\n    function setFeeRecipient(address _feeRecipient) external onlyManagement {\n        if (_feeRecipient == address(0)) revert ZeroAddress();\n        feeRecipient = _feeRecipient;\n    }\n\n    /// @notice Rescue a token from the contract. Usually used for tokens sent by a mistake.\n    /// @param token erc20 token\n    /// @param recipient recipient of the tokens\n    function recoverERC20(address token, address recipient) external onlyManagement {\n        if (token == address(_target)) revert ProtectedToken();\n        uint256 balance = IERC20(token).balanceOf(address(this));\n        IERC20(token).safeTransfer(recipient, balance);\n    }\n\n    /// @notice Pause issue, collect and updateUnclaimedYield\n    /// @dev only callable by management\n    function pause() external onlyManagement {\n        _pause();\n    }\n\n    /// @notice Unpause issue, collect and updateUnclaimedYield\n    /// @dev only callable by management\n    function unpause() external onlyManagement {\n        _unpause();\n    }\n\n    /* ================== INTERNAL METHODS =================== */\n    /* ================== UTIL METHODS =================== */\n\n    function _burnFrom(address owner, uint256 amount) internal {\n        if (owner != msg.sender) {\n            _spendAllowance(owner, msg.sender, amount);\n        }\n        _burn(owner, amount);\n    }\n\n    /// @notice Updates the global scales cache.\n    /// If the maturity has passed, updates the maturity scale `mscale` if it's not updated yet. (Settlement)\n    /// @return cscale The current scale of the adapter.\n    function _updateGlobalScalesCache(GlobalScales memory _cache) internal view returns (uint256) {\n        // Get the current scale of the adapter\n        uint256 cscale = adapter.scale();\n        if (_cache.mscale != 0) return cscale; // Skip if already settled\n\n        // If mscale == 0 and maturity has passed, settle the _cache.\n        if (block.timestamp >= maturity) {\n            _cache.mscale = cscale.toUint128();\n        }\n        // Update the _cache's maxscale\n        if (cscale > _cache.maxscale) {\n            _cache.maxscale = cscale.toUint128();\n        }\n        return cscale;\n    }\n\n    /// @notice Computes the amount of Target tokens to be redeemed for the given PT amount.\n    /// @dev This function is responsible for the logic of computing the amount of Target tokens to be redeemed.\n    /// @param _gscales Local cache of global scales.\n    /// @param _principalAmount PT amount to redeem in units of underlying tokens.\n    function _computeSharesRedeemed(\n        GlobalScales memory _gscales,\n        uint256 _principalAmount\n    ) internal pure returns (uint256) {\n        // Formula: shares = principalAmount / maxscale\n        return _principalAmount.divWadDown(_gscales.maxscale);\n    }\n\n    /// @notice Computes the amount of PT to be redeemed for the given shares amount.\n    /// @param _gscales Local cache of global scales.\n    /// @param _shares Amount of Target tokens equivalent to the amount of PT to be redeemed (in units of Target tokens).\n    function _computePrincipalTokenRedeemed(\n        GlobalScales memory _gscales,\n        uint256 _shares\n    ) internal pure returns (uint256) {\n        // Formula: principalAmount = shares * maxscale\n        return _shares.mulWadUp(_gscales.maxscale);\n    }\n\n    /// @notice Computes the amount of accrued interest in the Target.\n    /// e.g. if the Target scale increases by 5% since the last time the account collected and the account has 100 YT,\n    /// then the account will receive 100 * 5% = 5 Target as interest, which is equivalent to 5 * `maxscale` Underlying now.\n    /// @dev `_maxscale` should be updated before calling this function.\n    /// @param _maxscale The latest max scale of the series (assume non-zero).\n    /// @param _lscale The user-stored last scale (_lscale MUST be non-zero).\n    /// @param _yBal The user's current balance of Yield Token.\n    /// @return accruedInTarget The accrued interest in Target token. (rounded down)\n    function _computeAccruedInterestInTarget(\n        uint256 _maxscale,\n        uint256 _lscale,\n        uint256 _yBal\n    ) internal pure returns (uint256) {\n        // Hackmd: F5, F7\n        // Compute how much underlying has accrued since the last time this user collected, in units of Target.\n        // The scale is the amount of underlying per Target. `underlying = shares * scale`.\n        // Hackmd: F6\n        // Reminder: _lscale is the scale of the last time the user collected their yield.\n        // If the scale (price) of Target has increased since then (_maxscale > _lscale), the user has accrued some interest.\n\n        // The balance of YT `_yBal` represents the underlying amount a user has deposited into the yield source at the last collection.\n        // At the last collection, `_yBal` underlying was worth `_yBal / _lscale` in units of Target.\n        // Now, `_yBal` underlying is worth `_yBal / effMaxscale` in units of Target.\n        // The difference is the amount of interest accrued in units of Target.\n        // NOTE: The `yBal / maxscale` should be rounded up, which lets the `accrued` value round up, i.e., toward the protocol (against a user).\n        //       This is to prevent a user from withdrawing more shares than this contract has.\n        uint256 sharesNow = _yBal.divWadUp(_maxscale); // rounded up to prevent a user from withdrawing more shares than this contract has.\n        uint256 sharesDeposited = _yBal.divWadDown(_lscale);\n        if (sharesDeposited <= sharesNow) {\n            return 0;\n        }\n        return sharesDeposited - sharesNow; // rounded down\n    }\n}\n"
      },
      "src/YieldToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.19;\n\n// interfaces\nimport {IERC20} from \"@openzeppelin/contracts@4.9.3/token/ERC20/IERC20.sol\";\nimport {IYieldToken} from \"./interfaces/IYieldToken.sol\";\nimport {IBaseToken} from \"./interfaces/IBaseToken.sol\";\nimport {ITranche} from \"./interfaces/ITranche.sol\";\n// libs\nimport {SafeERC20Namer} from \"./utils/SafeERC20Namer.sol\";\n// inheriting\nimport {ERC20Permit, ERC20} from \"@openzeppelin/contracts@4.9.3/token/ERC20/extensions/ERC20Permit.sol\";\nimport {BaseToken} from \"./BaseToken.sol\";\n\n/// @title YieldToken\n/// @notice YieldToken is a token that represents the future yield of a Target (yield-bearing asset).\n///         It is minted when a user deposits into a Tranche and burned when the user redeems after maturity or when redeemed with PrincipalToken.\ncontract YieldToken is BaseToken, IYieldToken {\n    uint8 private immutable uDecimals;\n\n    address public immutable underlying;\n    address public immutable override tranche;\n    uint256 public immutable override(IBaseToken, BaseToken) maturity;\n    address public immutable override(IBaseToken, BaseToken) target;\n\n    modifier onlyTranche() {\n        if (msg.sender != tranche) revert OnlyTranche();\n        _;\n    }\n\n    /// @dev Assume YieldToken is deployed from a factory.\n    /// The constructor is `payable` to remove msg.value check and reduce gas cost at deployment time.\n    /// This is acceptable because the factory contract doesn't deploy Tranche with ETH.\n    ///\n    /// Cache Underlying token decimals in the constructor\n    /// Deployer SHOULD ensure that zero check and validity check is performed before deployment.\n    /// @param _tranche The address of the Tranche contract that mints this YieldToken\n    /// @param _underlying Underlying token address (zero-check SHOULD be performed in the Tranche contract)\n    /// @param _target Target token address  (zero-check SHOULD be performed in the Tranche contract)\n    /// @param _maturity Maturity timestamp (SHOULD be checked in the Tranche contract)\n    constructor(\n        address _tranche,\n        address _underlying,\n        address _target,\n        uint256 _maturity\n    ) payable ERC20(\"Napier Yield Token\", \"eYT\") ERC20Permit(\"Napier Yield Token\") {\n        underlying = _underlying;\n        tranche = _tranche;\n        maturity = _maturity;\n        target = _target;\n        uDecimals = ERC20(_underlying).decimals();\n    }\n\n    /* ================== MUTATIVE METHODS =================== */\n\n    /// @inheritdoc IYieldToken\n    function mint(address to, uint256 amount) external override onlyTranche {\n        _mint(to, amount);\n    }\n\n    /// @inheritdoc IYieldToken\n    function burn(address owner, uint256 amount) external override onlyTranche {\n        _burn(owner, amount);\n    }\n\n    /// @inheritdoc IYieldToken\n    function burnFrom(address owner, address spender, uint256 amount) external override onlyTranche {\n        if (owner != spender) {\n            _spendAllowance(owner, spender, amount);\n        }\n        _burn(owner, amount);\n    }\n\n    /// @inheritdoc ERC20\n    /// @notice This function reverts if Tranche is paused.\n    /// NOTE: This function is overridden to ensure that `msg.sender`'s and `to`'s unclaimed yields is updated.\n    function transfer(address to, uint256 amount) public override(ERC20, IERC20) returns (bool) {\n        ITranche(tranche).updateUnclaimedYield(msg.sender, to, amount);\n        return super.transfer(to, amount);\n    }\n\n    /// @inheritdoc ERC20\n    /// @notice This function reverts if Tranche is paused.\n    /// NOTE: This function is overridden to ensure that `from`'s and `to`'s unclaimed yields is updated.\n    ///       This is necessary to track the yield accrued by the user and to make YieldToken fungible.\n    /// @dev  Every time a user transfers their YieldToken, we will update `from` and `to`'s unclaimed yield.\n    ///       When someone transfers the YTs of `from` to `to`, The accrued yield at that time is stored for each account.\n    ///       users can later claim their respective accrued yield with `ITranche#collect()`.\n    function transferFrom(address from, address to, uint256 amount) public override(ERC20, IERC20) returns (bool) {\n        ITranche(tranche).updateUnclaimedYield(from, to, amount);\n        return super.transferFrom(from, to, amount);\n    }\n\n    /* ================== VIEW METHODS =================== */\n\n    /* ================== METADATA =================== */\n\n    /// @inheritdoc ERC20\n    function name() public view override returns (string memory) {\n        string memory tokenName = SafeERC20Namer.tokenName(target);\n        return string.concat(\"Napier Yield Token \", tokenName, \"@\", _toDateString(maturity));\n    }\n\n    /// @inheritdoc ERC20\n    function symbol() public view override returns (string memory) {\n        string memory tokenSymbol = SafeERC20Namer.tokenSymbol(target);\n        return string.concat(\"YT-\", tokenSymbol, \"@\", _toDateString(maturity));\n    }\n\n    function decimals() public view override returns (uint8) {\n        return uDecimals;\n    }\n}\n"
      },
      "src/interfaces/IERC5095.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts@4.9.3/token/ERC20/IERC20.sol\";\n\n/// @notice Principal tokens (zero-coupon tokens) are redeemable for a single underlying EIP-20 token at a future timestamp.\n///         https://eips.ethereum.org/EIPS/eip-5095\ninterface IERC5095 is IERC20 {\n    event Redeem(address indexed from, address indexed to, uint256 underlyingAmount);\n\n    /// @dev Asset that is returned on redemption.\n    function underlying() external view returns (address underlyingAddress);\n\n    /// @dev Unix time at which redemption of fyToken for underlying are possible\n    function maturity() external view returns (uint256 timestamp);\n\n    /// @dev Converts a specified amount of principal to underlying\n    function convertToUnderlying(uint256 principalAmount) external view returns (uint256 underlyingAmount);\n\n    /// @dev Converts a specified amount of underlying to principal\n    function convertToPrincipal(uint256 underlyingAmount) external view returns (uint256 principalAmount);\n\n    /// @dev Gives the maximum amount an address holder can redeem in terms of the principal\n    function maxRedeem(address holder) external view returns (uint256 maxPrincipalAmount);\n\n    /// @dev Gives the amount in terms of underlying that the princiapl amount can be redeemed for plus accrual\n    function previewRedeem(uint256 principalAmount) external view returns (uint256 underlyingAmount);\n\n    /// @dev Burn fyToken after maturity for an amount of principal.\n    function redeem(uint256 principalAmount, address to, address from) external returns (uint256 underlyingAmount);\n\n    /// @dev Gives the maximum amount an address holder can withdraw in terms of the underlying\n    function maxWithdraw(address holder) external view returns (uint256 maxUnderlyingAmount);\n\n    /// @dev Gives the amount in terms of principal that the underlying amount can be withdrawn for plus accrual\n    function previewWithdraw(uint256 underlyingAmount) external view returns (uint256 principalAmount);\n\n    /// @dev Burn fyToken after maturity for an amount of underlying.\n    function withdraw(uint256 underlyingAmount, address to, address from) external returns (uint256 principalAmount);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.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 IERC20 {\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"
      },
      "src/interfaces/IYieldToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport {IBaseToken} from \"./IBaseToken.sol\";\n\ninterface IYieldToken is IBaseToken {\n    error OnlyTranche();\n\n    function tranche() external view returns (address);\n\n    /// @notice mint yield token\n    /// @dev only tranche can mint yield token\n    /// @param to recipient of yield token\n    /// @param amount amount of yield token to mint\n    function mint(address to, uint256 amount) external;\n\n    /// @notice burn yield token of owner\n    /// @dev only tranche can burn yield token\n    /// @param owner owner of yield token\n    /// @param amount amount of yield token to burn\n    function burn(address owner, uint256 amount) external;\n\n    /// @notice spender burn yield token on behalf of owner\n    /// @notice owner must approve spender prior to calling this function\n    /// @dev only tranche can burn yield token\n    /// @param owner owner of yield token\n    /// @param spender address to burn yield token on behalf of owner\n    /// @param amount amount of yield token to burn\n    function burnFrom(address owner, address spender, uint256 amount) external;\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.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 Math {\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"
      },
      "src/utils/FixedPointMathLib.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\n/// @notice Taken from: https://github.com/transmissions11/solmate/blob/2001af43aedb46fdc2335d2a7714fb2dae7cfcd1/src/utils/FixedPointMathLib.sol\n\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\nlibrary FixedPointMathLib {\n    /*//////////////////////////////////////////////////////////////\n                    SIMPLIFIED FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal constant MAX_UINT256 = 2 ** 256 - 1;\n\n    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n    }\n\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n    }\n\n    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n    }\n\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    LOW LEVEL FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function mulDivDown(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // Divide x * y by the denominator.\n            z := div(mul(x, y), denominator)\n        }\n    }\n\n    function mulDivUp(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // If x * y modulo the denominator is strictly greater than 0,\n            // 1 is added to round up the division of x * y by the denominator.\n            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\n        }\n    }\n\n    function rpow(uint256 x, uint256 n, uint256 scalar) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            switch x\n            case 0 {\n                switch n\n                case 0 {\n                    // 0 ** 0 = 1\n                    z := scalar\n                }\n                default {\n                    // 0 ** n = 0\n                    z := 0\n                }\n            }\n            default {\n                switch mod(n, 2)\n                case 0 {\n                    // If n is even, store scalar in z for now.\n                    z := scalar\n                }\n                default {\n                    // If n is odd, store x in z for now.\n                    z := x\n                }\n\n                // Shifting right by 1 is like dividing by 2.\n                let half := shr(1, scalar)\n\n                for {\n                    // Shift n right by 1 before looping to halve it.\n                    n := shr(1, n)\n                } n {\n                    // Shift n right by 1 each iteration to halve it.\n                    n := shr(1, n)\n                } {\n                    // Revert immediately if x ** 2 would overflow.\n                    // Equivalent to iszero(eq(div(xx, x), x)) here.\n                    if shr(128, x) {\n                        revert(0, 0)\n                    }\n\n                    // Store x squared.\n                    let xx := mul(x, x)\n\n                    // Round to the nearest number.\n                    let xxRound := add(xx, half)\n\n                    // Revert if xx + half overflowed.\n                    if lt(xxRound, xx) {\n                        revert(0, 0)\n                    }\n\n                    // Set x to scaled xxRound.\n                    x := div(xxRound, scalar)\n\n                    // If n is even:\n                    if mod(n, 2) {\n                        // Compute z * x.\n                        let zx := mul(z, x)\n\n                        // If z * x overflowed:\n                        if iszero(eq(div(zx, x), z)) {\n                            // Revert if x is non-zero.\n                            if iszero(iszero(x)) {\n                                revert(0, 0)\n                            }\n                        }\n\n                        // Round to the nearest number.\n                        let zxRound := add(zx, half)\n\n                        // Revert if zx + half overflowed.\n                        if lt(zxRound, zx) {\n                            revert(0, 0)\n                        }\n\n                        // Return properly scaled zxRound.\n                        z := div(zxRound, scalar)\n                    }\n                }\n            }\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        GENERAL NUMBER UTILITIES\n    //////////////////////////////////////////////////////////////*/\n\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let y := x // We start y at x, which will help us make our initial estimate.\n\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // We check y >= 2^(k + 8) but shift right by k bits\n            // each branch to ensure that if x >= 256, then y >= 256.\n            if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n                y := shr(128, y)\n                z := shl(64, z)\n            }\n            if iszero(lt(y, 0x1000000000000000000)) {\n                y := shr(64, y)\n                z := shl(32, z)\n            }\n            if iszero(lt(y, 0x10000000000)) {\n                y := shr(32, y)\n                z := shl(16, z)\n            }\n            if iszero(lt(y, 0x1000000)) {\n                y := shr(16, y)\n                z := shl(8, z)\n            }\n\n            // Goal was to get z*z*y within a small factor of x. More iterations could\n            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n            // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n            // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n            // There is no overflow risk here since y < 2^136 after the first branch above.\n            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If x+1 is a perfect square, the Babylonian method cycles between\n            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Mod x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            z := mod(x, y)\n        }\n    }\n\n    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Divide x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            r := div(x, y)\n        }\n    }\n\n    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Add 1 to x * y if x % y > 0. Note this will\n            // return 0 instead of reverting if y is zero.\n            z := add(gt(mod(x, y), 0), div(x, y))\n        }\n    }\n}\n"
      },
      "src/utils/SafeERC20Namer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// Modified from: Uniswap Library\n// Use OpenZepplin's Strings library instead of the one from Uniswap\n// https://github.com/Uniswap/solidity-lib/blob/c01640b0f0f1d8a85cba8de378cc48469fcfd9a6/contracts/libraries/SafeERC20Namer.sol\n// https://github.com/yieldprotocol/yield-utils-v2/blob/dbeb85ac94befc477bf8cdff9f178fdf331eb83d/src/token/SafeERC20Namer.sol\n\npragma solidity ^0.8.0;\n\nimport {Strings} from \"@openzeppelin/contracts@4.9.3/utils/Strings.sol\";\n\n// produces token descriptors from inconsistent or absent ERC20 symbol implementations that can return string or bytes32\n// this library will always produce a string symbol to represent the token\nlibrary SafeERC20Namer {\n    function bytes32ToString(bytes32 x) private pure returns (string memory) {\n        bytes memory bytesString = new bytes(32);\n        uint256 charCount = 0;\n        for (uint256 j; j < 32; j++) {\n            bytes1 char = x[j];\n            if (char != 0) {\n                bytesString[charCount] = char;\n                charCount++;\n            }\n        }\n        bytes memory bytesStringTrimmed = new bytes(charCount);\n        for (uint256 j; j < charCount; j++) {\n            bytesStringTrimmed[j] = bytesString[j];\n        }\n        return string(bytesStringTrimmed);\n    }\n\n    // assumes the data is in position 2\n    function parseStringData(bytes memory b) private pure returns (string memory) {\n        uint256 charCount = 0;\n        // first parse the charCount out of the data\n        for (uint256 i = 32; i < 64; i++) {\n            charCount <<= 8;\n            charCount += uint8(b[i]);\n        }\n\n        bytes memory bytesStringTrimmed = new bytes(charCount);\n        for (uint256 i; i < charCount; i++) {\n            bytesStringTrimmed[i] = b[i + 64];\n        }\n\n        return string(bytesStringTrimmed);\n    }\n\n    // uses a heuristic to produce a token name from the address\n    // the heuristic returns the full hex of the address string in upper case\n    function addressToName(address token) private pure returns (string memory) {\n        return Strings.toHexString(token);\n    }\n\n    // uses a heuristic to produce a token symbol from the address\n    // the heuristic returns the first 6 hex of the address string in upper case\n    function addressToSymbol(address token) private pure returns (string memory) {\n        return Strings.toHexString(token);\n    }\n\n    // calls an external view token contract method that returns a symbol or name, and parses the output into a string\n    function callAndParseStringReturn(address token, bytes4 selector) private view returns (string memory) {\n        (bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(selector));\n        // if not implemented, or returns empty data, return empty string\n        if (!success || data.length == 0) {\n            return \"\";\n        }\n        // bytes32 data always has length 32\n        if (data.length == 32) {\n            bytes32 decoded = abi.decode(data, (bytes32));\n            return bytes32ToString(decoded);\n        } else if (data.length > 64) {\n            return abi.decode(data, (string));\n        }\n        return \"\";\n    }\n\n    // attempts to extract the token symbol. if it does not implement symbol, returns a symbol derived from the address\n    function tokenSymbol(address token) internal view returns (string memory) {\n        // 0x95d89b41 = bytes4(keccak256(\"symbol()\"))\n        string memory symbol = callAndParseStringReturn(token, 0x95d89b41);\n        if (bytes(symbol).length == 0) {\n            // fallback to 6 uppercase hex of address\n            return addressToSymbol(token);\n        }\n        return symbol;\n    }\n\n    // attempts to extract the token name. if it does not implement name, returns a name derived from the address\n    function tokenName(address token) internal view returns (string memory) {\n        // 0x06fdde03 = bytes4(keccak256(\"name()\"))\n        string memory name = callAndParseStringReturn(token, 0x06fdde03);\n        if (bytes(name).length == 0) {\n            // fallback to full hex of address\n            return addressToName(token);\n        }\n        return name;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.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 \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.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 SafeERC20 {\n    using Address 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(IERC20 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(IERC20 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(IERC20 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(IERC20 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(IERC20 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(IERC20 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        IERC20Permit 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(IERC20 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(IERC20 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))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/cryptography/EIP712.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation 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 * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n    using Counters for Counters.Counter;\n\n    mapping(address => Counters.Counter) private _nonces;\n\n    // solhint-disable-next-line var-name-mixedcase\n    bytes32 private constant _PERMIT_TYPEHASH =\n        keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n    /**\n     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n     * However, to ensure consistency with the upgradeable transpiler, we will continue\n     * to reserve a slot.\n     * @custom:oz-renamed-from _PERMIT_TYPEHASH\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\n\n    /**\n     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n     *\n     * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n     */\n    constructor(string memory name) EIP712(name, \"1\") {}\n\n    /**\n     * @dev See {IERC20Permit-permit}.\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    ) public virtual override {\n        require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n        bytes32 hash = _hashTypedDataV4(structHash);\n\n        address signer = ECDSA.recover(hash, v, r, s);\n        require(signer == owner, \"ERC20Permit: invalid signature\");\n\n        _approve(owner, spender, value);\n    }\n\n    /**\n     * @dev See {IERC20Permit-nonces}.\n     */\n    function nonces(address owner) public view virtual override returns (uint256) {\n        return _nonces[owner].current();\n    }\n\n    /**\n     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n        return _domainSeparatorV4();\n    }\n\n    /**\n     * @dev \"Consume a nonce\": return the current value and increment.\n     *\n     * _Available since v4.1._\n     */\n    function _useNonce(address owner) internal virtual returns (uint256 current) {\n        Counters.Counter storage nonce = _nonces[owner];\n        current = nonce.current();\n        nonce.increment();\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/security/Pausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\n    }\n}\n"
      },
      "src/BaseToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.19;\n\nimport {IBaseToken} from \"./interfaces/IBaseToken.sol\";\nimport {DateTime} from \"./utils/DateTime.sol\";\nimport {ERC20Permit} from \"@openzeppelin/contracts@4.9.3/token/ERC20/extensions/ERC20Permit.sol\";\n\nabstract contract BaseToken is ERC20Permit, IBaseToken {\n    /// @inheritdoc IBaseToken\n    function maturity() external view virtual returns (uint256);\n\n    /// @inheritdoc IBaseToken\n    function target() external view virtual returns (address);\n\n    function _toDateString(uint256 _maturity) internal pure returns (string memory) {\n        (string memory d, string memory m, string memory y) = DateTime.toDateString(_maturity);\n        return string.concat(d, \"-\", m, \"-\", y);\n    }\n}\n"
      },
      "src/interfaces/IBaseToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts@4.9.3/token/ERC20/IERC20.sol\";\n\n/// @title IBaseToken\n/// @notice token interface for Principal and Yield tokens\ninterface IBaseToken is IERC20 {\n    /// @notice maturity date of the token\n    function maturity() external view returns (uint256);\n\n    /// @notice target address of the token\n    function target() external view returns (address);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\ninterface IERC20Permit {\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    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"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.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 Address {\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"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n            mstore(0x1c, hash)\n            message := keccak256(0x00, 0x3c)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, \"\\x19\\x01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            data := keccak256(ptr, 0x42)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Data with intended validator, created from a\n     * `validator` and `data` according to the version 0 of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.8;\n\nimport \"./ECDSA.sol\";\nimport \"../ShortStrings.sol\";\nimport \"../../interfaces/IERC5267.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\n * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\n *\n * _Available since v3.4._\n *\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n */\nabstract contract EIP712 is IERC5267 {\n    using ShortStrings for *;\n\n    bytes32 private constant _TYPE_HASH =\n        keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n    // invalidate the cached domain separator if the chain id changes.\n    bytes32 private immutable _cachedDomainSeparator;\n    uint256 private immutable _cachedChainId;\n    address private immutable _cachedThis;\n\n    bytes32 private immutable _hashedName;\n    bytes32 private immutable _hashedVersion;\n\n    ShortString private immutable _name;\n    ShortString private immutable _version;\n    string private _nameFallback;\n    string private _versionFallback;\n\n    /**\n     * @dev Initializes the domain separator and parameter caches.\n     *\n     * The meaning of `name` and `version` is specified in\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n     *\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n     * - `version`: the current major version of the signing domain.\n     *\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n     * contract upgrade].\n     */\n    constructor(string memory name, string memory version) {\n        _name = name.toShortStringWithFallback(_nameFallback);\n        _version = version.toShortStringWithFallback(_versionFallback);\n        _hashedName = keccak256(bytes(name));\n        _hashedVersion = keccak256(bytes(version));\n\n        _cachedChainId = block.chainid;\n        _cachedDomainSeparator = _buildDomainSeparator();\n        _cachedThis = address(this);\n    }\n\n    /**\n     * @dev Returns the domain separator for the current chain.\n     */\n    function _domainSeparatorV4() internal view returns (bytes32) {\n        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\n            return _cachedDomainSeparator;\n        } else {\n            return _buildDomainSeparator();\n        }\n    }\n\n    function _buildDomainSeparator() private view returns (bytes32) {\n        return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\n    }\n\n    /**\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n     * function returns the hash of the fully encoded EIP712 message for this domain.\n     *\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n     *\n     * ```solidity\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n     *     keccak256(\"Mail(address to,string contents)\"),\n     *     mailTo,\n     *     keccak256(bytes(mailContents))\n     * )));\n     * address signer = ECDSA.recover(digest, signature);\n     * ```\n     */\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n    }\n\n    /**\n     * @dev See {EIP-5267}.\n     *\n     * _Available since v4.9._\n     */\n    function eip712Domain()\n        public\n        view\n        virtual\n        override\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        )\n    {\n        return (\n            hex\"0f\", // 01111\n            _name.toStringWithFallback(_nameFallback),\n            _version.toStringWithFallback(_versionFallback),\n            block.chainid,\n            address(this),\n            bytes32(0),\n            new uint256[](0)\n        );\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Counters.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n    struct Counter {\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\n        uint256 _value; // default: 0\n    }\n\n    function current(Counter storage counter) internal view returns (uint256) {\n        return counter._value;\n    }\n\n    function increment(Counter storage counter) internal {\n        unchecked {\n            counter._value += 1;\n        }\n    }\n\n    function decrement(Counter storage counter) internal {\n        uint256 value = counter._value;\n        require(value > 0, \"Counter: decrement overflow\");\n        unchecked {\n            counter._value = value - 1;\n        }\n    }\n\n    function reset(Counter storage counter) internal {\n        counter._value = 0;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "src/utils/DateTime.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\n// Taken from: https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\n\nlibrary DateTime {\n    uint256 constant SECONDS_PER_DAY = 24 * 60 * 60;\n    uint256 constant SECONDS_PER_HOUR = 60 * 60;\n    uint256 constant SECONDS_PER_MINUTE = 60;\n    int256 constant OFFSET19700101 = 2440588;\n\n    function timestampToDate(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day) {\n        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n\n    function timestampToDateTime(\n        uint256 timestamp\n    ) internal pure returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) {\n        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        uint256 secs = timestamp % SECONDS_PER_DAY;\n        hour = secs / SECONDS_PER_HOUR;\n        secs = secs % SECONDS_PER_HOUR;\n        minute = secs / SECONDS_PER_MINUTE;\n        second = secs % SECONDS_PER_MINUTE;\n    }\n\n    function toDateString(\n        uint256 _timestamp\n    ) internal pure returns (string memory d, string memory m, string memory y) {\n        (uint256 year, uint256 month, uint256 day) = timestampToDate(_timestamp);\n        d = uintToString(day);\n        m = uintToString(month);\n        y = uintToString(year);\n    }\n\n    function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) {\n        uint256 _days = timestamp / SECONDS_PER_DAY;\n        dayOfWeek = ((_days + 3) % 7) + 1;\n    }\n\n    /// Taken from https://stackoverflow.com/questions/47129173/how-to-convert-uint-to-string-in-solidity\n    function uintToString(uint256 _i) internal pure returns (string memory _uintAsString) {\n        if (_i == 0) {\n            return \"0\";\n        }\n        uint256 j = _i;\n        uint256 len;\n        while (j != 0) {\n            len++;\n            j /= 10;\n        }\n        bytes memory bstr = new bytes(len);\n        uint256 k = len;\n        while (_i != 0) {\n            k = k - 1;\n            uint8 temp = (48 + uint8(_i - (_i / 10) * 10));\n            bytes1 b1 = bytes1(temp);\n            bstr[k] = b1;\n            _i /= 10;\n        }\n        return string(bstr);\n    }\n\n    // ------------------------------------------------------------------------\n    // Calculate the number of days from 1970/01/01 to year/month/day using\n    // the date conversion algorithm from\n    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n    // and subtracting the offset 2440588 so that 1970/01/01 is day 0\n    //\n    // days = day\n    //      - 32075\n    //      + 1461 * (year + 4800 + (month - 14) / 12) / 4\n    //      + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\n    //      - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\n    //      - offset\n    // ------------------------------------------------------------------------\n    function _daysFromDate(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 _days) {\n        require(year >= 1970);\n        int256 _year = int256(year);\n        int256 _month = int256(month);\n        int256 _day = int256(day);\n\n        int256 __days = _day -\n            32075 +\n            (1461 * (_year + 4800 + (_month - 14) / 12)) /\n            4 +\n            (367 * (_month - 2 - ((_month - 14) / 12) * 12)) /\n            12 -\n            (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /\n            4 -\n            OFFSET19700101;\n\n        _days = uint256(__days);\n    }\n\n    // ------------------------------------------------------------------------\n    // Calculate year/month/day from the number of days since 1970/01/01 using\n    // the date conversion algorithm from\n    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n    // and adding the offset 2440588 so that 1970/01/01 is day 0\n    //\n    // int L = days + 68569 + offset\n    // int N = 4 * L / 146097\n    // L = L - (146097 * N + 3) / 4\n    // year = 4000 * (L + 1) / 1461001\n    // L = L - 1461 * year / 4 + 31\n    // month = 80 * L / 2447\n    // dd = L - 2447 * month / 80\n    // L = month / 11\n    // month = month + 2 - 12 * L\n    // year = 100 * (N - 49) + year + L\n    // ------------------------------------------------------------------------\n    function _daysToDate(uint256 _days) internal pure returns (uint256 year, uint256 month, uint256 day) {\n        int256 __days = int256(_days);\n\n        int256 L = __days + 68569 + OFFSET19700101;\n        int256 N = (4 * L) / 146097;\n        L = L - (146097 * N + 3) / 4;\n        int256 _year = (4000 * (L + 1)) / 1461001;\n        L = L - (1461 * _year) / 4 + 31;\n        int256 _month = (80 * L) / 2447;\n        int256 _day = L - (2447 * _month) / 80;\n        L = _month / 11;\n        _month = _month + 2 - 12 * L;\n        _year = 100 * (N - 49) + _year + L;\n\n        year = uint256(_year);\n        month = uint256(_month);\n        day = uint256(_day);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol)\n\npragma solidity ^0.8.8;\n\nimport \"./StorageSlot.sol\";\n\n// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |\n// | length  | 0x                                                              BB |\ntype ShortString is bytes32;\n\n/**\n * @dev This library provides functions to convert short memory strings\n * into a `ShortString` type that can be used as an immutable variable.\n *\n * Strings of arbitrary length can be optimized using this library if\n * they are short enough (up to 31 bytes) by packing them with their\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\n * fallback mechanism can be used for every other case.\n *\n * Usage example:\n *\n * ```solidity\n * contract Named {\n *     using ShortStrings for *;\n *\n *     ShortString private immutable _name;\n *     string private _nameFallback;\n *\n *     constructor(string memory contractName) {\n *         _name = contractName.toShortStringWithFallback(_nameFallback);\n *     }\n *\n *     function name() external view returns (string memory) {\n *         return _name.toStringWithFallback(_nameFallback);\n *     }\n * }\n * ```\n */\nlibrary ShortStrings {\n    // Used as an identifier for strings longer than 31 bytes.\n    bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\n\n    error StringTooLong(string str);\n    error InvalidShortString();\n\n    /**\n     * @dev Encode a string of at most 31 chars into a `ShortString`.\n     *\n     * This will trigger a `StringTooLong` error is the input string is too long.\n     */\n    function toShortString(string memory str) internal pure returns (ShortString) {\n        bytes memory bstr = bytes(str);\n        if (bstr.length > 31) {\n            revert StringTooLong(str);\n        }\n        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\n    }\n\n    /**\n     * @dev Decode a `ShortString` back to a \"normal\" string.\n     */\n    function toString(ShortString sstr) internal pure returns (string memory) {\n        uint256 len = byteLength(sstr);\n        // using `new string(len)` would work locally but is not memory safe.\n        string memory str = new string(32);\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(str, len)\n            mstore(add(str, 0x20), sstr)\n        }\n        return str;\n    }\n\n    /**\n     * @dev Return the length of a `ShortString`.\n     */\n    function byteLength(ShortString sstr) internal pure returns (uint256) {\n        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\n        if (result > 31) {\n            revert InvalidShortString();\n        }\n        return result;\n    }\n\n    /**\n     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\n     */\n    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\n        if (bytes(value).length < 32) {\n            return toShortString(value);\n        } else {\n            StorageSlot.getStringSlot(store).value = value;\n            return ShortString.wrap(_FALLBACK_SENTINEL);\n        }\n    }\n\n    /**\n     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.\n     */\n    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\n        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {\n            return toString(value);\n        } else {\n            return store;\n        }\n    }\n\n    /**\n     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}.\n     *\n     * WARNING: This will return the \"byte length\" of the string. This may not reflect the actual length in terms of\n     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\n     */\n    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\n        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {\n            return byteLength(value);\n        } else {\n            return bytes(store).length;\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)\n\npragma solidity ^0.8.0;\n\ninterface IERC5267 {\n    /**\n     * @dev MAY be emitted to signal that the domain could have changed.\n     */\n    event EIP712DomainChanged();\n\n    /**\n     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n     * signature.\n     */\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/",
        "@openzeppelin/contracts@4.9.3/=lib/openzeppelin-contracts/contracts/",
        "hardhat-deployer/=lib/hardhat-deployer/src/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "eth-gas-reporter/=node_modules/eth-gas-reporter/",
        "forge-std/=lib/forge-std/src/",
        "hardhat/=node_modules/hardhat/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 2000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {
        "src/Create2TrancheLib.sol": {
          "Create2TrancheLib": "0x09aaa7c384f2f7f315a8d9f87f5659360cb24e64"
        }
      }
    }
  }}