creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@maverickprotocol/maverick-v1-interfaces/contracts/interfaces/IFactory.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../interfaces/IPool.sol\";\nimport \"../interfaces/IPosition.sol\";\ninterface IFactory {\n    event PoolCreated(address poolAddress, uint256 fee, uint256 tickSpacing, int32 activeTick, int256 lookback, uint64 protocolFeeRatio, IERC20 tokenA, IERC20 tokenB);\n    event SetFactoryProtocolFeeRatio(uint64 protocolFeeRatio);\n    event SetFactoryOwner(address owner);\n    /// @notice creates new pool\n    /// @param _fee is a rate in prbmath 60x18 decimal format\n    /// @param _tickSpacing  1.0001^tickSpacing is the bin width\n    /// @param _activeTick initial activeTick of the pool\n    /// @param _lookback TWAP lookback in whole seconds\n    /// @param _tokenA ERC20 token\n    /// @param _tokenB ERC20 token\n    function create(\n        uint256 _fee,\n        uint256 _tickSpacing,\n        int256 _lookback,\n        int32 _activeTick,\n        IERC20 _tokenA,\n        IERC20 _tokenB\n    ) external returns (IPool);\n    function lookup(\n        uint256 fee,\n        uint256 tickSpacing,\n        int256 lookback,\n        IERC20 tokenA,\n        IERC20 tokenB\n    ) external view returns (IPool);\n    function owner() external view returns (address);\n    function position() external view returns (IPosition);\n    /// @notice protocolFeeRatio ratio of the swap fee that is kept for the\n    //protocol\n    function protocolFeeRatio() external view returns (uint64);\n    /// @notice lookup table for whether a pool is owned by the factory\n    function isFactoryPool(IPool pool) external view returns (bool);\n}\n"
      },
      "@maverickprotocol/maverick-v1-interfaces/contracts/interfaces/IPool.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./IFactory.sol\";\ninterface IPool {\n    event Swap(address sender, address recipient, bool tokenAIn, bool exactOutput, uint256 amountIn, uint256 amountOut, int32 activeTick);\n    event AddLiquidity(address indexed sender, uint256 indexed tokenId, BinDelta[] binDeltas);\n    event MigrateBinsUpStack(address indexed sender, uint128 binId, uint32 maxRecursion);\n    event TransferLiquidity(uint256 fromTokenId, uint256 toTokenId, RemoveLiquidityParams[] params);\n    event RemoveLiquidity(address indexed sender, address indexed recipient, uint256 indexed tokenId, BinDelta[] binDeltas);\n    event BinMerged(uint128 indexed binId, uint128 reserveA, uint128 reserveB, uint128 mergeId);\n    event BinMoved(uint128 indexed binId, int128 previousTick, int128 newTick);\n    event ProtocolFeeCollected(uint256 protocolFee, bool isTokenA);\n    event SetProtocolFeeRatio(uint256 protocolFee);\n    /// @notice return parameters for Add/Remove liquidity\n    /// @param binId of the bin that changed\n    /// @param kind one of the 4 Kinds (0=static, 1=right, 2=left, 3=both)\n    /// @param isActive bool to indicate whether the bin is still active\n    /// @param lowerTick is the lower price tick of the bin in its current state\n    /// @param deltaA amount of A token that has been added or removed\n    /// @param deltaB amount of B token that has been added or removed\n    /// @param deltaLpToken amount of LP balance that has increase (add) or decreased (remove)\n    struct BinDelta {\n        uint128 deltaA;\n        uint128 deltaB;\n        uint256 deltaLpBalance;\n        uint128 binId;\n        uint8 kind;\n        int32 lowerTick;\n        bool isActive;\n    }\n    /// @notice time weighted average state\n    /// @param twa the twa at the last update instant\n    /// @param value the new value that was passed in at the last update\n    /// @param lastTimestamp timestamp of the last update in seconds\n    /// @param lookback time in seconds\n    struct TwaState {\n        int96 twa;\n        int96 value;\n        uint64 lastTimestamp;\n    }\n    /// @notice bin state parameters\n    /// @param kind one of the 4 Kinds (0=static, 1=right, 2=left, 3=both)\n    /// @param lowerTick is the lower price tick of the bin in its current state\n    /// @param mergeId binId of the bin that this bin has merged in to\n    /// @param reserveA amount of A token in bin\n    /// @param reserveB amount of B token in bin\n    /// @param totalSupply total amount of LP tokens in this bin\n    /// @param mergeBinBalance LP token balance that this bin posseses of the merge bin\n    struct BinState {\n        uint128 reserveA;\n        uint128 reserveB;\n        uint128 mergeBinBalance;\n        uint128 mergeId;\n        uint128 totalSupply;\n        uint8 kind;\n        int32 lowerTick;\n    }\n    /// @notice Parameters for each bin that will get new liquidity\n    /// @param kind one of the 4 Kinds (0=static, 1=right, 2=left, 3=both)\n    /// @param pos bin position\n    /// @param isDelta bool that indicates whether the bin position is relative\n    //to the current bin or an absolute position\n    /// @param deltaA amount of A token to add\n    /// @param deltaB amount of B token to add\n    struct AddLiquidityParams {\n        uint8 kind;\n        int32 pos;\n        bool isDelta;\n        uint128 deltaA;\n        uint128 deltaB;\n    }\n    /// @notice Parameters for each bin that will have liquidity removed\n    /// @param binId index of the bin losing liquidity\n    /// @param amount LP balance amount to remove\n    struct RemoveLiquidityParams {\n        uint128 binId;\n        uint128 amount;\n    }\n    /// @notice State of the pool\n    /// @param activeTick  current bin position that contains the active bins\n    /// @param status pool status.  e.g. locked or unlocked; status values\n    //defined in Pool.sol\n    /// @param binCounter index of the last bin created\n    /// @param protocolFeeRatio ratio of the swap fee that is kept for the\n    //protocol\n    struct State {\n        int32 activeTick;\n        uint8 status;\n        uint128 binCounter;\n        uint64 protocolFeeRatio;\n    }\n    /// @notice fee for pool in 18 decimal format\n    function fee() external view returns (uint256);\n    /// @notice tickSpacing of pool where 1.0001^tickSpacing is the bin width\n    function tickSpacing() external view returns (uint256);\n    /// @notice address of token A\n    function tokenA() external view returns (IERC20);\n    /// @notice address of token B\n    function tokenB() external view returns (IERC20);\n    /// @notice address of Factory\n    function factory() external view returns (IFactory);\n    /// @notice bitmap of active bins\n    function binMap(int32 tick) external view returns (uint256);\n    /// @notice mapping of tick/kind to binId\n    function binPositions(int32 tick, uint256 kind) external view returns (uint128);\n    /// @notice internal accounting of the sum tokenA balance across bins\n    function binBalanceA() external view returns (uint128);\n    /// @notice internal accounting of the sum tokenB balance across bins\n    function binBalanceB() external view returns (uint128);\n    /// @notice Twa state values\n    function getTwa() external view returns (TwaState memory);\n    /// @notice log base binWidth of the time weighted average price\n    function getCurrentTwa() external view returns (int256);\n    /// @notice pool state\n    function getState() external view returns (State memory);\n    /// @notice Add liquidity to a pool.\n    /// @param tokenId NFT token ID that will hold the position\n    /// @param params array of AddLiquidityParams that specify the mode and\n    //position of the liquidity\n    /// @param data callback function that addLiquidity will call so that the\n    //caller can transfer tokens\n    function addLiquidity(\n        uint256 tokenId,\n        AddLiquidityParams[] calldata params,\n        bytes calldata data\n    )\n        external\n        returns (\n            uint256 tokenAAmount,\n            uint256 tokenBAmount,\n            BinDelta[] memory binDeltas\n        );\n    /// @notice Transfer liquidity in an array of bins from one nft tokenId\n    //to another\n    /// @param fromTokenId NFT token ID that holds the position being transferred\n    /// @param toTokenId NFT token ID that is receiving liquidity\n    /// @param params array of binIds and amounts to transfer\n    function transferLiquidity(\n        uint256 fromTokenId,\n        uint256 toTokenId,\n        RemoveLiquidityParams[] calldata params\n    ) external;\n    /// @notice Remove liquidity from a pool.\n    /// @param recipient address that will receive the removed tokens\n    /// @param tokenId NFT token ID that holds the position being removed\n    /// @param params array of RemoveLiquidityParams that specify the bins,\n    //and amounts\n    function removeLiquidity(\n        address recipient,\n        uint256 tokenId,\n        RemoveLiquidityParams[] calldata params\n    )\n        external\n        returns (\n            uint256 tokenAOut,\n            uint256 tokenBOut,\n            BinDelta[] memory binDeltas\n        );\n    /// @notice Migrate bins up the linked list of merged bins so that its\n    //mergeId is the currrent active bin.\n    /// @param binId is an array of the binIds to be migrated\n    /// @param maxRecursion is the maximum recursion depth of the migration. set to\n    //zero to recurse until the active bin is found.\n    function migrateBinUpStack(uint128 binId, uint32 maxRecursion) external;\n    /// @notice swap tokens\n    /// @param recipient address that will receive the output tokens\n    /// @param amount amount of token that is either the input if exactOutput\n    //is false or the output if exactOutput is true\n    /// @param tokenAIn bool indicating whether tokenA is the input\n    /// @param exactOutput bool indicating whether the amount specified is the\n    //exact output amount (true)\n    /// @param sqrtPriceLimit limiting sqrt price of the swap.  A value of 0\n    //indicates no limit.  Limit is only engaged for exactOutput=false.  If the\n    //limit is reached only part of the input amount will be swapped and the\n    //callback will only require that amount of the swap to be paid.\n    /// @param data callback function that swap will call so that the\n    //caller can transfer tokens\n    function swap(\n        address recipient,\n        uint256 amount,\n        bool tokenAIn,\n        bool exactOutput,\n        uint256 sqrtPriceLimit,\n        bytes calldata data\n    ) external returns (uint256 amountIn, uint256 amountOut);\n    /// @notice bin information for a given binId\n    function getBin(uint128 binId) external view returns (BinState memory bin);\n    /// @notice LP token balance for a given tokenId at a given binId\n    function balanceOf(uint256 tokenId, uint128 binId) external view returns (uint256 lpToken);\n    /// @notice tokenA scale value\n    /// @dev msb is a flag to indicate whether tokenA has more or less than 18\n    //decimals.  Scale is used in conjuction with Math.toScale/Math.fromScale\n    //functions to convert from token amounts to D18 scale internal pool\n    //accounting.\n    function tokenAScale() external view returns (uint256);\n    /// @notice tokenB scale value\n    /// @dev msb is a flag to indicate whether tokenA has more or less than 18\n    //decimals.  Scale is used in conjuction with Math.toScale/Math.fromScale\n    //functions to convert from token amounts to D18 scale internal pool\n    //accounting.\n    function tokenBScale() external view returns (uint256);\n}\n"
      },
      "@maverickprotocol/maverick-v1-interfaces/contracts/interfaces/IPosition.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\nimport \"../interfaces/IPositionMetadata.sol\";\ninterface IPosition is IERC721Enumerable {\n    event SetMetadata(IPositionMetadata metadata);\n    /// @notice mint new position NFT\n    function mint(address to) external returns (uint256 tokenId);\n    /// @notice mint new position NFT\n    function tokenOfOwnerByIndexExists(address owner, uint256 index) external view returns (bool);\n}\n"
      },
      "@maverickprotocol/maverick-v1-interfaces/contracts/interfaces/IPositionMetadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IPositionMetadata {\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (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        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\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"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-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"
      },
      "@openzeppelin/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"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-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    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) 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(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) 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    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\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        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n    /**\n     * @dev Returns the total amount of tokens stored by the contract.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n     * Use along with {totalSupply} to enumerate all tokens.\n     */\n    function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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     *\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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, \"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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) 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        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(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        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(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        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason 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            // 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}\n"
      },
      "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) 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                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\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(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) 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. It 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        // 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)`.\n        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n        // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n        // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1;\n        uint256 x = a;\n        if (x >> 128 > 0) {\n            x >>= 128;\n            result <<= 64;\n        }\n        if (x >> 64 > 0) {\n            x >>= 64;\n            result <<= 32;\n        }\n        if (x >> 32 > 0) {\n            x >>= 32;\n            result <<= 16;\n        }\n        if (x >> 16 > 0) {\n            x >>= 16;\n            result <<= 8;\n        }\n        if (x >> 8 > 0) {\n            x >>= 8;\n            result <<= 4;\n        }\n        if (x >> 4 > 0) {\n            x >>= 4;\n            result <<= 2;\n        }\n        if (x >> 2 > 0) {\n            result <<= 1;\n        }\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        uint256 result = sqrt(a);\n        if (rounding == Rounding.Up && result * result < a) {\n            result += 1;\n        }\n        return result;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Multicall.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Multicall.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Address.sol\";\n\n/**\n * @dev Provides a function to batch together multiple calls in a single external call.\n *\n * _Available since v4.1._\n */\nabstract contract Multicall {\n    /**\n     * @dev Receives and executes a batch of function calls on this contract.\n     */\n    function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {\n        results = new bytes[](data.length);\n        for (uint256 i = 0; i < data.length; i++) {\n            results[i] = Address.functionDelegateCall(address(this), data[i]);\n        }\n        return results;\n    }\n}\n"
      },
      "contracts/interfaces/IPoolPositionAndRewardFactorySlim.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IPool} from \"@maverickprotocol/maverick-v1-interfaces/contracts/interfaces/IPool.sol\";\nimport {IFactory} from \"@maverickprotocol/maverick-v1-interfaces/contracts/interfaces/IFactory.sol\";\n\nimport {IPoolPositionSlim} from \"./IPoolPositionSlim.sol\";\nimport {IReward} from \"./IReward.sol\";\n\ninterface IPoolPositionAndRewardFactorySlim {\n    event PoolPositionCreated(IPool pool, uint128[] binIds, uint128[] ratios, IPoolPositionSlim poolPosition, uint256 poolPositionNumber);\n\n    event LpRewardCreated(IPoolPositionSlim poolPosition, address reward);\n\n    event AddNewApprovedRewardToken(address rewardToken, uint256 minimumAmount);\n\n    struct RewardInfos {\n        IReward.RewardInfo[] rewardInfoList;\n    }\n\n    function allPoolPositions(uint256 poolPositionNumber) external view returns (IPoolPositionSlim poolPosition);\n\n    function poolPositionNumber(IPoolPositionSlim poolPosition) external view returns (uint256 poolPositionNumber);\n\n    function getLpRewardByPP(IPoolPositionSlim) external view returns (IReward);\n\n    function poolFactory() external view returns (IFactory);\n\n    function allPoolPositionsLength() external view returns (uint256);\n\n    function isApprovedRewardToken(address reward) external view returns (bool);\n\n    function minimumRewardAmount(address reward) external view returns (uint256);\n\n    function isPoolPosition(IPoolPositionSlim poolPosition) external view returns (bool);\n\n    function createPoolPositionAndRewards(IPool pool, uint128[] calldata binIds, uint128[] calldata ratios, bool isStatic) external returns (IPoolPositionSlim);\n\n    function owner() external view returns (address);\n}\n"
      },
      "contracts/interfaces/IPoolPositionSlim.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\nimport {IPool} from \"@maverickprotocol/maverick-v1-interfaces/contracts/interfaces/IPool.sol\";\n\ninterface IPoolPositionSlim is IERC20Metadata {\n    error InvalidBinIds(uint128[] binIds);\n    error InvalidRatio();\n    error BinIsMerged();\n    error InvalidTokenId(uint256 tokenId);\n\n    event MigrateBinLiquidity(uint128 oldBinId, uint128 newBinId);\n\n    function allBinIds() external view returns (uint128[] memory);\n\n    function binIds(uint256) external view returns (uint128);\n\n    function ratios(uint256) external view returns (uint128);\n\n    /// @notice tokenId that holds PP assets\n    function tokenId() external view returns (uint256);\n\n    /// @notice Pool that the position exists in\n    function pool() external view returns (IPool);\n\n    /// @notice Whether or not the PP contains all static bins as opposed to\n    //movement bins\n    function isStatic() external view returns (bool);\n\n    /// @notice Returns struct array of bin lp amounts that need to be transfered for a mint\n    /// @param  binZeroLpAddAmount LP amount of bin[0] to be added\n    function binLpAddAmountRequirement(uint128 binZeroLpAddAmount) external view returns (IPool.RemoveLiquidityParams[] memory params);\n\n    /// @notice Burns PoolPosition ERC20 tokens from given account and\n    //trasnfers Pool liquidity position to toTokenId\n    /// @param account wallet or contract whose PoolPosition tokens will be\n    //burned\n    /// @param toTokenId pool.position() that will own the output liquidity\n    /// @param lpAmountToUnStake number of PoolPosition LPs tokens to burn\n    function burnFromToTokenIdAsBinLiquidity(address account, uint256 toTokenId, uint256 lpAmountToUnStake) external returns (IPool.RemoveLiquidityParams[] memory params);\n\n    /// @notice Burns PoolPosition ERC20 tokens and trasnfers resulting\n    //liquidity as A/B tokens to recipient\n    /// @param account wallet or contract whose PoolPosition tokens will be\n    //burned\n    /// @param recipient pool.position() that will own the output tokens\n    /// @param lpAmountToUnStake number of PoolPosition LPs tokens to burn\n    function burnFromToAddressAsReserves(address account, address recipient, uint256 lpAmountToUnStake) external returns (uint256 amountA, uint256 amountB);\n\n    /// @notice Migrates the PoolPosition liquidity to active bin if the\n    //liquidity is currently merged\n    /// @dev Migrating only applies to one-bin dynamic-kind PoolPositions and\n    //it must be called before any other external call will execute if the bin\n    //in the PoolPosition has been merged.\n    function migrateBinLiquidity() external;\n\n    /// @notice Mint new PoolPosition tokens\n    /// @param to wallet or contract where PoolPosition tokens will be minted\n    /// @param fromTokenId pool.position() that will contribute input liquidity\n    /// @param binZeroLpAddAmount LP balance of pool.position() in PoolPosition\n    //bins[0] to be transfered\n    //  @return liquidity number of PoolPosition LP tokens minted\n    function mint(address to, uint256 fromTokenId, uint128 binZeroLpAddAmount) external returns (uint256 liquidity);\n\n    /// @notice Amount of pool.tokenA() and pool.tokenB() tokens held by the\n    //PoolPosition\n    //  @return reserveA Amount of pool.tokenA() tokens held by the\n    //  PoolPosition\n    //  @return reserveB Amount of pool.tokenB() tokens held by the\n    //  PoolPosition\n    function getReserves() external view returns (uint256 reserveA, uint256 reserveB);\n}\n"
      },
      "contracts/interfaces/IReward.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IReward {\n    event NotifyRewardAmount(address sender, address rewardTokenAddress, uint256 amount, uint256 duration, uint256 rewardRate);\n    event GetReward(address sender, address account, address recipient, uint8 rewardTokenIndex, address rewardTokenAddress, uint256 rewardPaid);\n    event UnStake(address sender, address account, uint256 amount, address recipient, uint256 userBalance, uint256 totalSupply);\n    event Stake(address sender, address supplier, uint256 amount, address account, uint256 userBalance, uint256 totalSupply);\n    event AddRewardToken(address rewardTokenAddress, uint8 rewardTokenIndex);\n    event RemoveRewardToken(address rewardTokenAddress, uint8 rewardTokenIndex);\n\n    error DurationOutOfBounds(uint256 duration);\n    error OnlyFactoryOwner();\n    error ZeroAmount();\n    error NotValidRewardToken(address rewardTokenAddress);\n    error TooManyRewardTokens();\n    error StaleToken(uint8 rewardTokenIndex);\n    error TokenNotStale(uint8 rewardTokenIndex);\n    error RewardStillActive(uint8 rewardTokenIndex);\n    error RewardAmountBelowThreshold(uint256 amount, uint256 minimumAmount);\n\n    struct RewardInfo {\n        // Timestamp of when the rewards finish\n        uint256 finishAt;\n        // Minimum of last updated time and reward finish time\n        uint256 updatedAt;\n        // Reward to be paid out per second\n        uint256 rewardRate;\n        // Sum of (reward rate * dt * 1e18 / total supply)\n        uint256 rewardPerTokenStored;\n        IERC20 rewardToken;\n    }\n\n    struct EarnedInfo {\n        // account\n        address account;\n        // earned\n        uint256 earned;\n        // reward token\n        IERC20 rewardToken;\n    }\n\n    function rewardInfo() external view returns (RewardInfo[] memory);\n\n    function tokenIndex(address tokenAddress) external view returns (uint8);\n\n    function balanceOf(address account) external view returns (uint256);\n\n    function earned(address account, address rewardTokenAddress) external view returns (uint256);\n\n    function earned(address account) external view returns (EarnedInfo[] memory earnedInfo);\n\n    /// @notice Add rewards tokens account the pot of rewards with a transferFrom.\n    /// @param  rewardTokenAddress address of reward token added\n    function notifyAndTransfer(address rewardTokenAddress, uint256 amount, uint256 duration) external;\n\n    /// @notice Deposit LP tokens for reward allocation.\n    /// @param amount LP token amount account deposit.\n    /// @param account The receiver of `amount` deposit benefit.\n    function stake(uint256 amount, address account) external;\n\n    /// @notice Withdraw LP token stake.\n    /// @param amount LP token amount account withdraw.\n    /// @param  recipient Receiver of the LP tokens.\n    function unstake(uint256 amount, address recipient) external;\n\n    /// @notice Withdraw entire amount of LP token stake.\n    /// @param  recipient Receiver of the LP tokens.\n    function unstakeAll(address recipient) external;\n\n    /// @notice Get reward proceeds for transaction sender account `account`.\n    /// @param recipient Receiver of REWARD_TOKEN rewards.\n    /// @param rewardTokenIndices indices of reward tokens to collect\n    function getReward(address recipient, uint8[] calldata rewardTokenIndices) external;\n\n    /// @notice Get reward proceeds for transaction sender account `account`.\n    /// @param recipient Receiver of REWARD_TOKEN rewards.\n    /// @param rewardTokenIndex index of reward token to collect\n    function getReward(address recipient, uint8 rewardTokenIndex) external returns (uint256);\n\n    /// @notice Remove stale tokens from the reward contract\n    /// @param rewardTokenIndex is the index of the reward token in the\n    //tokenIndex mapping\n    function removeStaleToken(uint8 rewardTokenIndex) external;\n}\n"
      },
      "contracts/libraries/BitMap.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// modified from OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/BitMaps.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential.\n * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].\n */\nlibrary BitMap {\n    struct Instance {\n        uint256 _data;\n    }\n\n    /**\n     * @dev Returns whether the bit at `index` is set.\n     */\n    function get(Instance storage self, uint8 index) internal view returns (bool) {\n        uint256 mask = 1 << index;\n        return self._data & mask != 0;\n    }\n\n    /**\n     * @dev Sets the bit at `index`.\n     */\n    function set(Instance storage self, uint8 index) internal {\n        uint256 mask = 1 << index;\n        self._data |= mask;\n    }\n\n    /**\n     * @dev Unsets the bit at `index`.\n     */\n    function unset(Instance storage self, uint8 index) internal {\n        uint256 mask = 1 << index;\n        self._data &= ~mask;\n    }\n}\n"
      },
      "contracts/libraries/Math.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\nimport {PRBMath} from \"prb-math/contracts/PRBMath.sol\";\nimport {PRBMathUD60x18} from \"prb-math/contracts/PRBMathUD60x18.sol\";\n\nlibrary Math {\n    using PRBMathUD60x18 for uint256;\n    uint256 constant MAX_BIT = 0x8000000000000000000000000000000000000000000000000000000000000000;\n    uint256 constant DEFAULT_SCALE = 1;\n\n    function max(uint256 x, uint256 y) internal pure returns (uint256) {\n        return x > y ? x : y;\n    }\n\n    function min(uint256 x, uint256 y) internal pure returns (uint256) {\n        return x < y ? x : y;\n    }\n\n    function mulDiv(uint256 x, uint256 y, uint256 k, bool ceil) internal pure returns (uint256 result) {\n        result = PRBMath.mulDiv(x, y, k);\n        if (ceil && mulmod(x, y, k) != 0) result = result + 1;\n    }\n\n    function clip(uint256 x, uint256 y) internal pure returns (uint256) {\n        return x < y ? 0 : x - y;\n    }\n\n    function toScale(uint256 amount, uint256 scaleFactor, bool ceil) internal pure returns (uint256) {\n        if (scaleFactor == DEFAULT_SCALE || amount == 0) {\n            return amount;\n        } else if ((scaleFactor & MAX_BIT) != 0) {\n            return amount * (scaleFactor & ~MAX_BIT);\n        } else {\n            return (ceil && mulmod(amount, 1, scaleFactor) != 0) ? amount / scaleFactor + 1 : amount / scaleFactor;\n        }\n    }\n\n    function fromScale(uint256 amount, uint256 scaleFactor) internal pure returns (uint256) {\n        if (scaleFactor == DEFAULT_SCALE) {\n            return amount;\n        } else if ((scaleFactor & MAX_BIT) != 0) {\n            return amount / (scaleFactor & ~MAX_BIT);\n        } else {\n            return amount * scaleFactor;\n        }\n    }\n\n    function tickSqrtPrice(uint256 tickSpacing, int32 _tick) internal pure returns (uint256 _result) {\n        unchecked {\n            uint256 tick = _tick < 0 ? uint256(-int256(_tick)) : uint256(int256(_tick));\n            tick *= tickSpacing;\n            uint256 ratio = tick & 0x1 != 0 ? 0xfffcb933bd6fad9d3af5f0b9f25db4d6 : 0x100000000000000000000000000000000;\n            if (tick & 0x2 != 0) ratio = (ratio * 0xfff97272373d41fd789c8cb37ffcaa1c) >> 128;\n            if (tick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656ac9229c67059486f389) >> 128;\n            if (tick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e81259b3cddc7a064941) >> 128;\n            if (tick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f67b19e8887e0bd251eb7) >> 128;\n            if (tick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98cd2e57b660be99eb2c4a) >> 128;\n            if (tick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c9838804e327cb417cafcb) >> 128;\n            if (tick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99d51e2cc356c2f617dbe0) >> 128;\n            if (tick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900aecf64236ab31f1f9dcb5) >> 128;\n            if (tick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac4d9194200696907cf2e37) >> 128;\n            if (tick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b88206f8abe8a3b44dd9be) >> 128;\n            if (tick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c578ef4f1d17b2b235d480) >> 128;\n            if (tick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd254ee83bdd3f248e7e785e) >> 128;\n            if (tick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d8f7dd10e744d913d033333) >> 128;\n            if (tick & 0x4000 != 0) ratio = (ratio * 0x70d869a156ddd32a39e257bc3f50aa9b) >> 128;\n            if (tick & 0x8000 != 0) ratio = (ratio * 0x31be135f97da6e09a19dc367e3b6da40) >> 128;\n            if (tick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7e5a9780b0cc4e25d61a56) >> 128;\n            if (tick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedbcb3a6ccb7ce618d14225) >> 128;\n            if (tick & 0x40000 != 0) ratio = (ratio * 0x2216e584f630389b2052b8db590e) >> 128;\n            if (_tick > 0) ratio = type(uint256).max / ratio;\n            _result = (ratio * PRBMathUD60x18.SCALE) >> 128;\n        }\n    }\n\n    function getTickL(uint256 _reserveA, uint256 _reserveB, uint256 _sqrtLowerTickPrice, uint256 _sqrtUpperTickPrice) internal pure returns (uint256) {\n        uint256 precisionBump = 0;\n        if ((_reserveA >> 60) == 0 && (_reserveB >> 60) == 0) {\n            precisionBump = 40;\n            _reserveA <<= precisionBump;\n            _reserveB <<= precisionBump;\n        }\n        if (_reserveA == 0 || _reserveB == 0) {\n            uint256 b = (_reserveA.div(_sqrtUpperTickPrice) + _reserveB.mul(_sqrtLowerTickPrice));\n            return mulDiv(b, _sqrtUpperTickPrice, _sqrtUpperTickPrice - _sqrtLowerTickPrice, false) >> precisionBump;\n        } else {\n            uint256 b = (_reserveA.div(_sqrtUpperTickPrice) + _reserveB.mul(_sqrtLowerTickPrice)) >> 1;\n            uint256 diff = _sqrtUpperTickPrice - _sqrtLowerTickPrice;\n            return mulDiv(b + (b.mul(b) + mulDiv(_reserveB.mul(_reserveA), diff, _sqrtUpperTickPrice, false)).sqrt(), _sqrtUpperTickPrice, diff, false) >> precisionBump;\n        }\n    }\n\n    function getTickSqrtPriceAndL(uint256 _reserveA, uint256 _reserveB, uint256 _sqrtLowerTickPrice, uint256 _sqrtUpperTickPrice) internal pure returns (uint256 sqrtPrice, uint256 liquidity) {\n        liquidity = getTickL(_reserveA, _reserveB, _sqrtLowerTickPrice, _sqrtUpperTickPrice);\n        if (_reserveA == 0) {\n            return (_sqrtLowerTickPrice, liquidity);\n        }\n        if (_reserveB == 0) {\n            return (_sqrtUpperTickPrice, liquidity);\n        }\n        sqrtPrice = ((_reserveA + liquidity.mul(_sqrtLowerTickPrice)).div(_reserveB + liquidity.div(_sqrtUpperTickPrice))).sqrt();\n        sqrtPrice = min(max(sqrtPrice, _sqrtLowerTickPrice), _sqrtUpperTickPrice);\n    }\n}\n"
      },
      "contracts/RewardBase.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// adapted from https://github.com/Synthetixio/synthetix/blob/c53070db9a93e5717ca7f74fcaf3922e991fb71b/contracts/StakingRewards.sol\npragma solidity ^0.8.0;\n\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport {Multicall} from \"@openzeppelin/contracts/utils/Multicall.sol\";\n\nimport {IReward} from \"./interfaces/IReward.sol\";\nimport {Math as MavMath} from \"./libraries/Math.sol\";\nimport {BitMap} from \"./libraries/BitMap.sol\";\nimport {IPoolPositionAndRewardFactorySlim} from \"./interfaces/IPoolPositionAndRewardFactorySlim.sol\";\n\nabstract contract RewardBase is IReward, ReentrancyGuard, Multicall {\n    using SafeERC20 for IERC20;\n    using BitMap for BitMap.Instance;\n\n    uint8 public MAX_REWARD_TOKENS = 16;\n    uint256 constant ONE = 1e18;\n    // after this period of time without a reward, users can remove token from\n    // list\n    uint256 constant STALE_INTERVAL = 30 days;\n\n    IPoolPositionAndRewardFactorySlim public immutable rewardFactory;\n    IERC20 public immutable stakingToken;\n\n    // Max Duration of rewards to be paid out\n    uint256 constant MAX_DURATION = 30 days;\n    uint256 constant MIN_DURATION = 3 days;\n\n    // Total staked\n    uint256 public totalSupply;\n    // User address => staked amount\n    mapping(address => uint256) public balanceOf;\n\n    struct RewardData {\n        // Timestamp of when the rewards finish\n        uint256 finishAt;\n        // Minimum of last updated time and reward finish time\n        uint256 updatedAt;\n        // Reward to be paid out per second\n        uint256 rewardRate;\n        // Sum of (reward rate * dt * 1e18 / total supply)\n        uint256 rewardPerTokenStored;\n        // User address => rewardPerTokenStored\n        mapping(address => uint256) userRewardPerTokenPaid;\n        // User address => rewards to be claimed\n        mapping(address => uint256) rewards;\n        // User address => rewards mapping to track if token index has been\n        // updated\n        mapping(address => uint256) resetCount;\n        // total earned\n        uint256 escrowedReward;\n        uint256 globalResetCount;\n        IERC20 rewardToken;\n    }\n    RewardData[] public rewardData;\n    mapping(address => uint8) public tokenIndex;\n\n    BitMap.Instance public globalActive;\n\n    constructor(IERC20 _stakingToken, IPoolPositionAndRewardFactorySlim _rewardFactory) {\n        stakingToken = _stakingToken;\n\n        rewardFactory = _rewardFactory;\n        // push empty token so that we can use index zero as a sentinel value\n        // in tokenIndex mapping; ie if tokenIndex[X] = 0, we know X is not in\n        // the list\n        rewardData.push();\n    }\n\n    modifier checkAmount(uint256 amount) {\n        if (amount == 0) revert ZeroAmount();\n        _;\n    }\n\n    /////////////////////////////////////\n    /// View Functions\n    /////////////////////////////////////\n\n    function rewardInfo() external view returns (RewardInfo[] memory info) {\n        uint256 length = rewardData.length;\n        info = new RewardInfo[](length);\n        for (uint8 i = 1; i < length; i++) {\n            RewardData storage data = rewardData[i];\n            info[i] = RewardInfo({finishAt: data.finishAt, updatedAt: data.updatedAt, rewardRate: data.rewardRate, rewardPerTokenStored: data.rewardPerTokenStored, rewardToken: data.rewardToken});\n        }\n    }\n\n    function earned(address account) public view returns (EarnedInfo[] memory earnedInfo) {\n        uint256 length = rewardData.length;\n        earnedInfo = new EarnedInfo[](length);\n        for (uint8 i = 1; i < length; i++) {\n            RewardData storage data = rewardData[i];\n            earnedInfo[i] = EarnedInfo({account: account, earned: earned(account, data), rewardToken: data.rewardToken});\n        }\n    }\n\n    function earned(address account, address rewardTokenAddress) external view returns (uint256) {\n        uint256 rewardTokenIndex = tokenIndex[rewardTokenAddress];\n        if (rewardTokenIndex == 0) revert NotValidRewardToken(rewardTokenAddress);\n        RewardData storage data = rewardData[rewardTokenIndex];\n        return earned(account, data);\n    }\n\n    function earned(address account, RewardData storage data) internal view returns (uint256) {\n        return data.rewards[account] + Math.mulDiv(balanceOf[account], MavMath.clip(data.rewardPerTokenStored + deltaRewardPerToken(data), data.userRewardPerTokenPaid[account]), ONE);\n    }\n\n    /////////////////////////////////////\n    /// Internal Update Functions\n    /////////////////////////////////////\n\n    function updateReward(address account, RewardData storage data) internal {\n        uint256 reward = deltaRewardPerToken(data);\n        if (reward != 0) {\n            data.rewardPerTokenStored += reward;\n            data.escrowedReward += Math.mulDiv(reward, totalSupply, ONE, Math.Rounding(1));\n        }\n        data.updatedAt = lastTimeRewardApplicable(data.finishAt);\n\n        if (account != address(0)) {\n            if (data.resetCount[account] != data.globalResetCount) {\n                // check to see if this token index was changed\n                data.userRewardPerTokenPaid[account] = 0;\n                data.rewards[account] = 0;\n                data.resetCount[account] = data.globalResetCount;\n            }\n            data.rewards[account] += deltaEarned(account, data);\n            data.userRewardPerTokenPaid[account] = data.rewardPerTokenStored;\n        }\n    }\n\n    function deltaEarned(address account, RewardData storage data) internal view returns (uint256) {\n        return Math.mulDiv(balanceOf[account], MavMath.clip(data.rewardPerTokenStored, data.userRewardPerTokenPaid[account]), ONE);\n    }\n\n    function deltaRewardPerToken(RewardData storage data) internal view returns (uint256) {\n        uint256 timeDiff = MavMath.clip(lastTimeRewardApplicable(data.finishAt), data.updatedAt);\n        if (timeDiff == 0 || totalSupply == 0 || data.rewardRate == 0) {\n            return 0;\n        }\n        return Math.mulDiv(data.rewardRate, timeDiff * ONE, totalSupply);\n    }\n\n    function lastTimeRewardApplicable(uint256 dataFinishAt) internal view returns (uint256) {\n        return Math.min(dataFinishAt, block.timestamp);\n    }\n\n    function updateAllRewards(address account) internal {\n        uint256 length = rewardData.length;\n        for (uint8 i = 1; i < length; i++) {\n            if (!globalActive.get(i)) continue;\n\n            RewardData storage data = rewardData[i];\n\n            updateReward(account, data);\n        }\n    }\n\n    /// @dev add token if it is approved and is not already tracked\n    function _checkAndAddRewardToken(address rewardTokenAddress) internal returns (uint8 rewardTokenIndex) {\n        rewardTokenIndex = tokenIndex[rewardTokenAddress];\n        if (rewardTokenIndex != 0) return rewardTokenIndex;\n\n        if (!rewardFactory.isApprovedRewardToken(rewardTokenAddress)) revert NotValidRewardToken(rewardTokenAddress);\n\n        // find first unset token index and use it\n        for (uint8 i = 1; i < MAX_REWARD_TOKENS + 1; i++) {\n            if (globalActive.get(i)) continue;\n            rewardTokenIndex = i;\n            break;\n        }\n        if (rewardTokenIndex == 0) revert TooManyRewardTokens();\n        if (rewardTokenIndex == rewardData.length) rewardData.push();\n\n        RewardData storage _data = rewardData[rewardTokenIndex];\n\n        _data.rewardToken = IERC20(rewardTokenAddress);\n        _data.globalResetCount++;\n\n        tokenIndex[rewardTokenAddress] = rewardTokenIndex;\n        globalActive.set(rewardTokenIndex);\n        emit AddRewardToken(rewardTokenAddress, rewardTokenIndex);\n    }\n\n    /////////////////////////////////////\n    /// Internal User Functions\n    /////////////////////////////////////\n\n    function _stake(address supplier, uint256 amount, address account) internal nonReentrant checkAmount(amount) {\n        updateAllRewards(account);\n        stakingToken.safeTransferFrom(supplier, address(this), amount);\n        balanceOf[account] += amount;\n        totalSupply += amount;\n        emit Stake(msg.sender, supplier, amount, account, balanceOf[account], totalSupply);\n    }\n\n    function _unstake(address account, uint256 amount, address recipient) internal nonReentrant checkAmount(amount) {\n        updateAllRewards(account);\n        balanceOf[account] -= amount;\n        totalSupply -= amount;\n        stakingToken.safeTransfer(recipient, amount);\n        emit UnStake(msg.sender, account, amount, recipient, balanceOf[account], totalSupply);\n    }\n\n    function _unstakeAll(address account, address recipient) internal {\n        _unstake(account, balanceOf[account], recipient);\n    }\n\n    function _getReward(address account, address recipient, uint8 rewardTokenIndex) internal nonReentrant returns (uint256 reward) {\n        if (!globalActive.get(rewardTokenIndex)) revert StaleToken(rewardTokenIndex);\n        RewardData storage data = rewardData[rewardTokenIndex];\n        updateReward(account, data);\n        reward = data.rewards[account];\n        if (reward != 0) {\n            data.rewards[account] = 0;\n            data.escrowedReward -= reward;\n            data.rewardToken.safeTransfer(recipient, reward);\n        }\n        emit GetReward(msg.sender, account, recipient, rewardTokenIndex, address(data.rewardToken), reward);\n    }\n\n    function _getReward(address account, address recipient, uint8[] memory rewardTokenIndices) internal {\n        uint256 length = rewardTokenIndices.length;\n        for (uint8 i; i < length; i++) {\n            _getReward(account, recipient, rewardTokenIndices[i]);\n        }\n    }\n\n    /////////////////////////////////////\n    /// Add Reward\n    /////////////////////////////////////\n\n    /// @notice Adds reward to contract.\n    function notifyAndTransfer(address rewardTokenAddress, uint256 amount, uint256 duration) public nonReentrant {\n        if (duration < MIN_DURATION) revert DurationOutOfBounds(duration);\n\n        uint256 minimumAmount = rewardFactory.minimumRewardAmount(rewardTokenAddress);\n        if (amount < minimumAmount) revert RewardAmountBelowThreshold(amount, minimumAmount);\n\n        duration = _notifyRewardAmount(rewardTokenAddress, amount, duration);\n\n        if (duration > MAX_DURATION) revert DurationOutOfBounds(duration);\n        IERC20(rewardTokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n    }\n\n    /* @notice called by reward depositor to recompute the reward rate.  If\n     *  notifier sends more than remaining amount, then notifier sets the rate.\n     *  Else, we extend the duration at the current rate. We may notify with less\n     *  than enough of assets to cover the period. In that case, reward rate will\n     *  be 0 and the assets sit on the contract until another notify happens with\n     *  enough assets for a positive rate.\n     *   @dev Must notify before transfering assets.  Transfering and then\n     *  notifying with the same amount will break the logic of this reward\n     *  contract.  If a contract needs to transfer and then notify, the\n     *  notification amount should be 0.\n     */\n    function _notifyRewardAmount(address rewardTokenAddress, uint256 amount, uint256 duration) internal returns (uint256) {\n        uint8 rewardTokenIndex = _checkAndAddRewardToken(rewardTokenAddress);\n        RewardData storage data = rewardData[rewardTokenIndex];\n        updateReward(address(0), data);\n        uint256 remainingRewards = MavMath.clip(data.rewardToken.balanceOf(address(this)), data.escrowedReward);\n\n        if (amount > remainingRewards || data.rewardRate == 0) {\n            // if notifying new amount, notifier gets to set the rate\n            data.rewardRate = (amount + remainingRewards) / duration;\n        } else {\n            // if notifier doesn't bring enough, we extend the duration at the\n            // same rate\n            duration = (amount + remainingRewards) / data.rewardRate;\n        }\n\n        data.finishAt = block.timestamp + duration;\n        data.updatedAt = block.timestamp;\n        emit NotifyRewardAmount(msg.sender, rewardTokenAddress, amount, duration, data.rewardRate);\n        return duration;\n    }\n\n    /////////////////////////////////////\n    /// Admin Function\n    /////////////////////////////////////\n\n    function removeStaleToken(uint8 rewardTokenIndex) public virtual nonReentrant {\n        _removeStaleToken(rewardTokenIndex);\n    }\n\n    function _removeStaleToken(uint8 rewardTokenIndex) internal {\n        RewardData storage data = rewardData[rewardTokenIndex];\n        if (block.timestamp < STALE_INTERVAL + data.finishAt) revert TokenNotStale(rewardTokenIndex);\n        emit RemoveRewardToken(address(data.rewardToken), rewardTokenIndex);\n\n        // remove token from list\n        globalActive.unset(rewardTokenIndex);\n        delete tokenIndex[address(data.rewardToken)];\n\n        delete data.rewardToken;\n        delete data.escrowedReward;\n        delete data.rewardPerTokenStored;\n        delete data.rewardRate;\n        delete data.finishAt;\n        delete data.updatedAt;\n    }\n}\n"
      },
      "contracts/RewardOpenSlim.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport {IPoolPositionAndRewardFactorySlim} from \"./interfaces/IPoolPositionAndRewardFactorySlim.sol\";\nimport {RewardBase} from \"./RewardBase.sol\";\n\ncontract RewardOpenSlim is RewardBase {\n    constructor(IERC20 _stakingToken, IPoolPositionAndRewardFactorySlim _rewardFactory) RewardBase(_stakingToken, _rewardFactory) {}\n\n    function stake(uint256 amount, address account) external {\n        _stake(msg.sender, amount, account);\n    }\n\n    function unstake(uint256 amount, address recipient) external {\n        _unstake(msg.sender, amount, recipient);\n    }\n\n    function unstakeAll(address recipient) external {\n        _unstakeAll(msg.sender, recipient);\n    }\n\n    function getReward(address recipient, uint8[] calldata rewardTokenIndices) external {\n        _getReward(msg.sender, recipient, rewardTokenIndices);\n    }\n\n    function getReward(address recipient, uint8 rewardTokenIndex) external returns (uint256) {\n        return _getReward(msg.sender, recipient, rewardTokenIndex);\n    }\n}\n"
      },
      "prb-math/contracts/PRBMath.sol": {
        "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\n/// @notice Emitted when the result overflows uint256.\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\n\n/// @notice Emitted when the result overflows uint256.\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\n\n/// @notice Emitted when one of the inputs is type(int256).min.\nerror PRBMath__MulDivSignedInputTooSmall();\n\n/// @notice Emitted when the intermediary absolute result overflows int256.\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is MIN_SD59x18.\nerror PRBMathSD59x18__AbsInputTooSmall();\n\n/// @notice Emitted when ceiling a number overflows SD59x18.\nerror PRBMathSD59x18__CeilOverflow(int256 x);\n\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\nerror PRBMathSD59x18__DivInputTooSmall();\n\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is greater than 133.084258667509499441.\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\n\n/// @notice Emitted when the input is greater than 192.\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\n\n/// @notice Emitted when flooring a number underflows SD59x18.\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\n\n/// @notice Emitted when the product of the inputs is negative.\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\n\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\n\n/// @notice Emitted when the input is less than or equal to zero.\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\n\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\nerror PRBMathSD59x18__MulInputTooSmall();\n\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\n\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is negative.\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\n\n/// @notice Emitted when the calculating the square root overflows SD59x18.\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\n\n/// @notice Emitted when addition overflows UD60x18.\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\n\n/// @notice Emitted when ceiling a number overflows UD60x18.\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\n\n/// @notice Emitted when the input is greater than 133.084258667509499441.\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\n\n/// @notice Emitted when the input is greater than 192.\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\n\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\n\n/// @notice Emitted when the input is less than 1.\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\n\n/// @notice Emitted when the calculating the square root overflows UD60x18.\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\n\n/// @notice Emitted when subtraction underflows UD60x18.\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\n\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\nlibrary PRBMath {\n    /// STRUCTS ///\n\n    struct SD59x18 {\n        int256 value;\n    }\n\n    struct UD60x18 {\n        uint256 value;\n    }\n\n    /// STORAGE ///\n\n    /// @dev How many trailing decimals can be represented.\n    uint256 internal constant SCALE = 1e18;\n\n    /// @dev Largest power of two divisor of SCALE.\n    uint256 internal constant SCALE_LPOTD = 262144;\n\n    /// @dev SCALE inverted mod 2^256.\n    uint256 internal constant SCALE_INVERSE =\n        78156646155174841979727994598816262306175212592076161876661_508869554232690281;\n\n    /// FUNCTIONS ///\n\n    /// @notice Calculates the binary exponent of x using the binary fraction method.\n    /// @dev Has to use 192.64-bit fixed-point numbers.\n    /// See https://ethereum.stackexchange.com/a/96594/24693.\n    /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\n    /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n    function exp2(uint256 x) internal pure returns (uint256 result) {\n        unchecked {\n            // Start from 0.5 in the 192.64-bit fixed-point format.\n            result = 0x800000000000000000000000000000000000000000000000;\n\n            // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\n            // because the initial result is 2^191 and all magic factors are less than 2^65.\n            if (x & 0x8000000000000000 > 0) {\n                result = (result * 0x16A09E667F3BCC909) >> 64;\n            }\n            if (x & 0x4000000000000000 > 0) {\n                result = (result * 0x1306FE0A31B7152DF) >> 64;\n            }\n            if (x & 0x2000000000000000 > 0) {\n                result = (result * 0x1172B83C7D517ADCE) >> 64;\n            }\n            if (x & 0x1000000000000000 > 0) {\n                result = (result * 0x10B5586CF9890F62A) >> 64;\n            }\n            if (x & 0x800000000000000 > 0) {\n                result = (result * 0x1059B0D31585743AE) >> 64;\n            }\n            if (x & 0x400000000000000 > 0) {\n                result = (result * 0x102C9A3E778060EE7) >> 64;\n            }\n            if (x & 0x200000000000000 > 0) {\n                result = (result * 0x10163DA9FB33356D8) >> 64;\n            }\n            if (x & 0x100000000000000 > 0) {\n                result = (result * 0x100B1AFA5ABCBED61) >> 64;\n            }\n            if (x & 0x80000000000000 > 0) {\n                result = (result * 0x10058C86DA1C09EA2) >> 64;\n            }\n            if (x & 0x40000000000000 > 0) {\n                result = (result * 0x1002C605E2E8CEC50) >> 64;\n            }\n            if (x & 0x20000000000000 > 0) {\n                result = (result * 0x100162F3904051FA1) >> 64;\n            }\n            if (x & 0x10000000000000 > 0) {\n                result = (result * 0x1000B175EFFDC76BA) >> 64;\n            }\n            if (x & 0x8000000000000 > 0) {\n                result = (result * 0x100058BA01FB9F96D) >> 64;\n            }\n            if (x & 0x4000000000000 > 0) {\n                result = (result * 0x10002C5CC37DA9492) >> 64;\n            }\n            if (x & 0x2000000000000 > 0) {\n                result = (result * 0x1000162E525EE0547) >> 64;\n            }\n            if (x & 0x1000000000000 > 0) {\n                result = (result * 0x10000B17255775C04) >> 64;\n            }\n            if (x & 0x800000000000 > 0) {\n                result = (result * 0x1000058B91B5BC9AE) >> 64;\n            }\n            if (x & 0x400000000000 > 0) {\n                result = (result * 0x100002C5C89D5EC6D) >> 64;\n            }\n            if (x & 0x200000000000 > 0) {\n                result = (result * 0x10000162E43F4F831) >> 64;\n            }\n            if (x & 0x100000000000 > 0) {\n                result = (result * 0x100000B1721BCFC9A) >> 64;\n            }\n            if (x & 0x80000000000 > 0) {\n                result = (result * 0x10000058B90CF1E6E) >> 64;\n            }\n            if (x & 0x40000000000 > 0) {\n                result = (result * 0x1000002C5C863B73F) >> 64;\n            }\n            if (x & 0x20000000000 > 0) {\n                result = (result * 0x100000162E430E5A2) >> 64;\n            }\n            if (x & 0x10000000000 > 0) {\n                result = (result * 0x1000000B172183551) >> 64;\n            }\n            if (x & 0x8000000000 > 0) {\n                result = (result * 0x100000058B90C0B49) >> 64;\n            }\n            if (x & 0x4000000000 > 0) {\n                result = (result * 0x10000002C5C8601CC) >> 64;\n            }\n            if (x & 0x2000000000 > 0) {\n                result = (result * 0x1000000162E42FFF0) >> 64;\n            }\n            if (x & 0x1000000000 > 0) {\n                result = (result * 0x10000000B17217FBB) >> 64;\n            }\n            if (x & 0x800000000 > 0) {\n                result = (result * 0x1000000058B90BFCE) >> 64;\n            }\n            if (x & 0x400000000 > 0) {\n                result = (result * 0x100000002C5C85FE3) >> 64;\n            }\n            if (x & 0x200000000 > 0) {\n                result = (result * 0x10000000162E42FF1) >> 64;\n            }\n            if (x & 0x100000000 > 0) {\n                result = (result * 0x100000000B17217F8) >> 64;\n            }\n            if (x & 0x80000000 > 0) {\n                result = (result * 0x10000000058B90BFC) >> 64;\n            }\n            if (x & 0x40000000 > 0) {\n                result = (result * 0x1000000002C5C85FE) >> 64;\n            }\n            if (x & 0x20000000 > 0) {\n                result = (result * 0x100000000162E42FF) >> 64;\n            }\n            if (x & 0x10000000 > 0) {\n                result = (result * 0x1000000000B17217F) >> 64;\n            }\n            if (x & 0x8000000 > 0) {\n                result = (result * 0x100000000058B90C0) >> 64;\n            }\n            if (x & 0x4000000 > 0) {\n                result = (result * 0x10000000002C5C860) >> 64;\n            }\n            if (x & 0x2000000 > 0) {\n                result = (result * 0x1000000000162E430) >> 64;\n            }\n            if (x & 0x1000000 > 0) {\n                result = (result * 0x10000000000B17218) >> 64;\n            }\n            if (x & 0x800000 > 0) {\n                result = (result * 0x1000000000058B90C) >> 64;\n            }\n            if (x & 0x400000 > 0) {\n                result = (result * 0x100000000002C5C86) >> 64;\n            }\n            if (x & 0x200000 > 0) {\n                result = (result * 0x10000000000162E43) >> 64;\n            }\n            if (x & 0x100000 > 0) {\n                result = (result * 0x100000000000B1721) >> 64;\n            }\n            if (x & 0x80000 > 0) {\n                result = (result * 0x10000000000058B91) >> 64;\n            }\n            if (x & 0x40000 > 0) {\n                result = (result * 0x1000000000002C5C8) >> 64;\n            }\n            if (x & 0x20000 > 0) {\n                result = (result * 0x100000000000162E4) >> 64;\n            }\n            if (x & 0x10000 > 0) {\n                result = (result * 0x1000000000000B172) >> 64;\n            }\n            if (x & 0x8000 > 0) {\n                result = (result * 0x100000000000058B9) >> 64;\n            }\n            if (x & 0x4000 > 0) {\n                result = (result * 0x10000000000002C5D) >> 64;\n            }\n            if (x & 0x2000 > 0) {\n                result = (result * 0x1000000000000162E) >> 64;\n            }\n            if (x & 0x1000 > 0) {\n                result = (result * 0x10000000000000B17) >> 64;\n            }\n            if (x & 0x800 > 0) {\n                result = (result * 0x1000000000000058C) >> 64;\n            }\n            if (x & 0x400 > 0) {\n                result = (result * 0x100000000000002C6) >> 64;\n            }\n            if (x & 0x200 > 0) {\n                result = (result * 0x10000000000000163) >> 64;\n            }\n            if (x & 0x100 > 0) {\n                result = (result * 0x100000000000000B1) >> 64;\n            }\n            if (x & 0x80 > 0) {\n                result = (result * 0x10000000000000059) >> 64;\n            }\n            if (x & 0x40 > 0) {\n                result = (result * 0x1000000000000002C) >> 64;\n            }\n            if (x & 0x20 > 0) {\n                result = (result * 0x10000000000000016) >> 64;\n            }\n            if (x & 0x10 > 0) {\n                result = (result * 0x1000000000000000B) >> 64;\n            }\n            if (x & 0x8 > 0) {\n                result = (result * 0x10000000000000006) >> 64;\n            }\n            if (x & 0x4 > 0) {\n                result = (result * 0x10000000000000003) >> 64;\n            }\n            if (x & 0x2 > 0) {\n                result = (result * 0x10000000000000001) >> 64;\n            }\n            if (x & 0x1 > 0) {\n                result = (result * 0x10000000000000001) >> 64;\n            }\n\n            // We're doing two things at the same time:\n            //\n            //   1. Multiply the result by 2^n + 1, where \"2^n\" is the integer part and the one is added to account for\n            //      the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\n            //      rather than 192.\n            //   2. Convert the result to the unsigned 60.18-decimal fixed-point format.\n            //\n            // This works because 2^(191-ip) = 2^ip / 2^191, where \"ip\" is the integer part \"2^n\".\n            result *= SCALE;\n            result >>= (191 - (x >> 64));\n        }\n    }\n\n    /// @notice Finds the zero-based index of the first one in the binary representation of x.\n    /// @dev See the note on msb in the \"Find First Set\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\n    /// @param x The uint256 number for which to find the index of the most significant bit.\n    /// @return msb The index of the most significant bit as an uint256.\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        if (x >= 2**128) {\n            x >>= 128;\n            msb += 128;\n        }\n        if (x >= 2**64) {\n            x >>= 64;\n            msb += 64;\n        }\n        if (x >= 2**32) {\n            x >>= 32;\n            msb += 32;\n        }\n        if (x >= 2**16) {\n            x >>= 16;\n            msb += 16;\n        }\n        if (x >= 2**8) {\n            x >>= 8;\n            msb += 8;\n        }\n        if (x >= 2**4) {\n            x >>= 4;\n            msb += 4;\n        }\n        if (x >= 2**2) {\n            x >>= 2;\n            msb += 2;\n        }\n        if (x >= 2**1) {\n            // No need to shift x any more.\n            msb += 1;\n        }\n    }\n\n    /// @notice Calculates floor(x*y÷denominator) with full precision.\n    ///\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\n    ///\n    /// Requirements:\n    /// - The denominator cannot be zero.\n    /// - The result must fit within uint256.\n    ///\n    /// Caveats:\n    /// - This function does not work with fixed-point numbers.\n    ///\n    /// @param x The multiplicand as an uint256.\n    /// @param y The multiplier as an uint256.\n    /// @param denominator The divisor as an uint256.\n    /// @return result The result as an uint256.\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 result) {\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            unchecked {\n                result = prod0 / denominator;\n            }\n            return result;\n        }\n\n        // Make sure the result is less than 2^256. Also prevents denominator == 0.\n        if (prod1 >= denominator) {\n            revert PRBMath__MulDivOverflow(prod1, denominator);\n        }\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        unchecked {\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 lpotdod = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by lpotdod.\n                denominator := div(denominator, lpotdod)\n\n                // Divide [prod1 prod0] by lpotdod.\n                prod0 := div(prod0, lpotdod)\n\n                // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\n                lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * lpotdod;\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    /// @notice Calculates floor(x*y÷1e18) with full precision.\n    ///\n    /// @dev Variant of \"mulDiv\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\n    /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\n    /// being rounded to 1e-18.  See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717.\n    ///\n    /// Requirements:\n    /// - The result must fit within uint256.\n    ///\n    /// Caveats:\n    /// - The body is purposely left uncommented; see the NatSpec comments in \"PRBMath.mulDiv\" to understand how this works.\n    /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\n    ///     1. x * y = type(uint256).max * SCALE\n    ///     2. (x * y) % SCALE >= SCALE / 2\n    ///\n    /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n    /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n    /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n    function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\n        uint256 prod0;\n        uint256 prod1;\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        if (prod1 >= SCALE) {\n            revert PRBMath__MulDivFixedPointOverflow(prod1);\n        }\n\n        uint256 remainder;\n        uint256 roundUpUnit;\n        assembly {\n            remainder := mulmod(x, y, SCALE)\n            roundUpUnit := gt(remainder, 499999999999999999)\n        }\n\n        if (prod1 == 0) {\n            unchecked {\n                result = (prod0 / SCALE) + roundUpUnit;\n                return result;\n            }\n        }\n\n        assembly {\n            result := add(\n                mul(\n                    or(\n                        div(sub(prod0, remainder), SCALE_LPOTD),\n                        mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\n                    ),\n                    SCALE_INVERSE\n                ),\n                roundUpUnit\n            )\n        }\n    }\n\n    /// @notice Calculates floor(x*y÷denominator) with full precision.\n    ///\n    /// @dev An extension of \"mulDiv\" for signed numbers. Works by computing the signs and the absolute values separately.\n    ///\n    /// Requirements:\n    /// - None of the inputs can be type(int256).min.\n    /// - The result must fit within int256.\n    ///\n    /// @param x The multiplicand as an int256.\n    /// @param y The multiplier as an int256.\n    /// @param denominator The divisor as an int256.\n    /// @return result The result as an int256.\n    function mulDivSigned(\n        int256 x,\n        int256 y,\n        int256 denominator\n    ) internal pure returns (int256 result) {\n        if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\n            revert PRBMath__MulDivSignedInputTooSmall();\n        }\n\n        // Get hold of the absolute values of x, y and the denominator.\n        uint256 ax;\n        uint256 ay;\n        uint256 ad;\n        unchecked {\n            ax = x < 0 ? uint256(-x) : uint256(x);\n            ay = y < 0 ? uint256(-y) : uint256(y);\n            ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\n        }\n\n        // Compute the absolute value of (x*y)÷denominator. The result must fit within int256.\n        uint256 rAbs = mulDiv(ax, ay, ad);\n        if (rAbs > uint256(type(int256).max)) {\n            revert PRBMath__MulDivSignedOverflow(rAbs);\n        }\n\n        // Get the signs of x, y and the denominator.\n        uint256 sx;\n        uint256 sy;\n        uint256 sd;\n        assembly {\n            sx := sgt(x, sub(0, 1))\n            sy := sgt(y, sub(0, 1))\n            sd := sgt(denominator, sub(0, 1))\n        }\n\n        // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\n        // If yes, the result should be negative.\n        result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\n    }\n\n    /// @notice Calculates the square root of x, rounding down.\n    /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n    ///\n    /// Caveats:\n    /// - This function does not work with fixed-point numbers.\n    ///\n    /// @param x The uint256 number for which to calculate the square root.\n    /// @return result The result as an uint256.\n    function sqrt(uint256 x) internal pure returns (uint256 result) {\n        if (x == 0) {\n            return 0;\n        }\n\n        // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\n        uint256 xAux = uint256(x);\n        result = 1;\n        if (xAux >= 0x100000000000000000000000000000000) {\n            xAux >>= 128;\n            result <<= 64;\n        }\n        if (xAux >= 0x10000000000000000) {\n            xAux >>= 64;\n            result <<= 32;\n        }\n        if (xAux >= 0x100000000) {\n            xAux >>= 32;\n            result <<= 16;\n        }\n        if (xAux >= 0x10000) {\n            xAux >>= 16;\n            result <<= 8;\n        }\n        if (xAux >= 0x100) {\n            xAux >>= 8;\n            result <<= 4;\n        }\n        if (xAux >= 0x10) {\n            xAux >>= 4;\n            result <<= 2;\n        }\n        if (xAux >= 0x8) {\n            result <<= 1;\n        }\n\n        // The operations can never overflow because the result is max 2^127 when it enters this block.\n        unchecked {\n            result = (result + x / result) >> 1;\n            result = (result + x / result) >> 1;\n            result = (result + x / result) >> 1;\n            result = (result + x / result) >> 1;\n            result = (result + x / result) >> 1;\n            result = (result + x / result) >> 1;\n            result = (result + x / result) >> 1; // Seven iterations should be enough\n            uint256 roundedDownResult = x / result;\n            return result >= roundedDownResult ? roundedDownResult : result;\n        }\n    }\n}\n"
      },
      "prb-math/contracts/PRBMathUD60x18.sol": {
        "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"./PRBMath.sol\";\n\n/// @title PRBMathUD60x18\n/// @author Paul Razvan Berg\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\n/// maximum values permitted by the Solidity type uint256.\nlibrary PRBMathUD60x18 {\n    /// @dev Half the SCALE number.\n    uint256 internal constant HALF_SCALE = 5e17;\n\n    /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\n    uint256 internal constant LOG2_E = 1_442695040888963407;\n\n    /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\n    uint256 internal constant MAX_UD60x18 =\n        115792089237316195423570985008687907853269984665640564039457_584007913129639935;\n\n    /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\n    uint256 internal constant MAX_WHOLE_UD60x18 =\n        115792089237316195423570985008687907853269984665640564039457_000000000000000000;\n\n    /// @dev How many trailing decimals can be represented.\n    uint256 internal constant SCALE = 1e18;\n\n    /// @notice Calculates the arithmetic average of x and y, rounding down.\n    /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\n    /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\n    /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\n    function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\n        // The operations can never overflow.\n        unchecked {\n            // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\n            // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\n            result = (x >> 1) + (y >> 1) + (x & y & 1);\n        }\n    }\n\n    /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\n    ///\n    /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\n    /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n    ///\n    /// Requirements:\n    /// - x must be less than or equal to MAX_WHOLE_UD60x18.\n    ///\n    /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\n    /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\n    function ceil(uint256 x) internal pure returns (uint256 result) {\n        if (x > MAX_WHOLE_UD60x18) {\n            revert PRBMathUD60x18__CeilOverflow(x);\n        }\n        assembly {\n            // Equivalent to \"x % SCALE\" but faster.\n            let remainder := mod(x, SCALE)\n\n            // Equivalent to \"SCALE - remainder\" but faster.\n            let delta := sub(SCALE, remainder)\n\n            // Equivalent to \"x + delta * (remainder > 0 ? 1 : 0)\" but faster.\n            result := add(x, mul(delta, gt(remainder, 0)))\n        }\n    }\n\n    /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\n    ///\n    /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\n    ///\n    /// Requirements:\n    /// - The denominator cannot be zero.\n    ///\n    /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\n    /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\n    /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\n    function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\n        result = PRBMath.mulDiv(x, SCALE, y);\n    }\n\n    /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\n    /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\n    function e() internal pure returns (uint256 result) {\n        result = 2_718281828459045235;\n    }\n\n    /// @notice Calculates the natural exponent of x.\n    ///\n    /// @dev Based on the insight that e^x = 2^(x * log2(e)).\n    ///\n    /// Requirements:\n    /// - All from \"log2\".\n    /// - x must be less than 133.084258667509499441.\n    ///\n    /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\n    /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n    function exp(uint256 x) internal pure returns (uint256 result) {\n        // Without this check, the value passed to \"exp2\" would be greater than 192.\n        if (x >= 133_084258667509499441) {\n            revert PRBMathUD60x18__ExpInputTooBig(x);\n        }\n\n        // Do the fixed-point multiplication inline to save gas.\n        unchecked {\n            uint256 doubleScaleProduct = x * LOG2_E;\n            result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\n        }\n    }\n\n    /// @notice Calculates the binary exponent of x using the binary fraction method.\n    ///\n    /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\n    ///\n    /// Requirements:\n    /// - x must be 192 or less.\n    /// - The result must fit within MAX_UD60x18.\n    ///\n    /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\n    /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n    function exp2(uint256 x) internal pure returns (uint256 result) {\n        // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\n        if (x >= 192e18) {\n            revert PRBMathUD60x18__Exp2InputTooBig(x);\n        }\n\n        unchecked {\n            // Convert x to the 192.64-bit fixed-point format.\n            uint256 x192x64 = (x << 64) / SCALE;\n\n            // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\n            result = PRBMath.exp2(x192x64);\n        }\n    }\n\n    /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\n    /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\n    /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n    /// @param x The unsigned 60.18-decimal fixed-point number to floor.\n    /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\n    function floor(uint256 x) internal pure returns (uint256 result) {\n        assembly {\n            // Equivalent to \"x % SCALE\" but faster.\n            let remainder := mod(x, SCALE)\n\n            // Equivalent to \"x - remainder * (remainder > 0 ? 1 : 0)\" but faster.\n            result := sub(x, mul(remainder, gt(remainder, 0)))\n        }\n    }\n\n    /// @notice Yields the excess beyond the floor of x.\n    /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\n    /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\n    /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\n    function frac(uint256 x) internal pure returns (uint256 result) {\n        assembly {\n            result := mod(x, SCALE)\n        }\n    }\n\n    /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\n    ///\n    /// @dev Requirements:\n    /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\n    ///\n    /// @param x The basic integer to convert.\n    /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\n    function fromUint(uint256 x) internal pure returns (uint256 result) {\n        unchecked {\n            if (x > MAX_UD60x18 / SCALE) {\n                revert PRBMathUD60x18__FromUintOverflow(x);\n            }\n            result = x * SCALE;\n        }\n    }\n\n    /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\n    ///\n    /// @dev Requirements:\n    /// - x * y must fit within MAX_UD60x18, lest it overflows.\n    ///\n    /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\n    /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\n    /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n    function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\n        if (x == 0) {\n            return 0;\n        }\n\n        unchecked {\n            // Checking for overflow this way is faster than letting Solidity do it.\n            uint256 xy = x * y;\n            if (xy / x != y) {\n                revert PRBMathUD60x18__GmOverflow(x, y);\n            }\n\n            // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\n            // during multiplication. See the comments within the \"sqrt\" function.\n            result = PRBMath.sqrt(xy);\n        }\n    }\n\n    /// @notice Calculates 1 / x, rounding toward zero.\n    ///\n    /// @dev Requirements:\n    /// - x cannot be zero.\n    ///\n    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\n    /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\n    function inv(uint256 x) internal pure returns (uint256 result) {\n        unchecked {\n            // 1e36 is SCALE * SCALE.\n            result = 1e36 / x;\n        }\n    }\n\n    /// @notice Calculates the natural logarithm of x.\n    ///\n    /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\n    ///\n    /// Requirements:\n    /// - All from \"log2\".\n    ///\n    /// Caveats:\n    /// - All from \"log2\".\n    /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\n    ///\n    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\n    /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\n    function ln(uint256 x) internal pure returns (uint256 result) {\n        // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\n        // can return is 196205294292027477728.\n        unchecked {\n            result = (log2(x) * SCALE) / LOG2_E;\n        }\n    }\n\n    /// @notice Calculates the common logarithm of x.\n    ///\n    /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\n    /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\n    ///\n    /// Requirements:\n    /// - All from \"log2\".\n    ///\n    /// Caveats:\n    /// - All from \"log2\".\n    ///\n    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\n    /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\n    function log10(uint256 x) internal pure returns (uint256 result) {\n        if (x < SCALE) {\n            revert PRBMathUD60x18__LogInputTooSmall(x);\n        }\n\n        // Note that the \"mul\" in this block is the assembly multiplication operation, not the \"mul\" function defined\n        // in this contract.\n        // prettier-ignore\n        assembly {\n            switch x\n            case 1 { result := mul(SCALE, sub(0, 18)) }\n            case 10 { result := mul(SCALE, sub(1, 18)) }\n            case 100 { result := mul(SCALE, sub(2, 18)) }\n            case 1000 { result := mul(SCALE, sub(3, 18)) }\n            case 10000 { result := mul(SCALE, sub(4, 18)) }\n            case 100000 { result := mul(SCALE, sub(5, 18)) }\n            case 1000000 { result := mul(SCALE, sub(6, 18)) }\n            case 10000000 { result := mul(SCALE, sub(7, 18)) }\n            case 100000000 { result := mul(SCALE, sub(8, 18)) }\n            case 1000000000 { result := mul(SCALE, sub(9, 18)) }\n            case 10000000000 { result := mul(SCALE, sub(10, 18)) }\n            case 100000000000 { result := mul(SCALE, sub(11, 18)) }\n            case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\n            case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\n            case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\n            case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\n            case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\n            case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\n            case 1000000000000000000 { result := 0 }\n            case 10000000000000000000 { result := SCALE }\n            case 100000000000000000000 { result := mul(SCALE, 2) }\n            case 1000000000000000000000 { result := mul(SCALE, 3) }\n            case 10000000000000000000000 { result := mul(SCALE, 4) }\n            case 100000000000000000000000 { result := mul(SCALE, 5) }\n            case 1000000000000000000000000 { result := mul(SCALE, 6) }\n            case 10000000000000000000000000 { result := mul(SCALE, 7) }\n            case 100000000000000000000000000 { result := mul(SCALE, 8) }\n            case 1000000000000000000000000000 { result := mul(SCALE, 9) }\n            case 10000000000000000000000000000 { result := mul(SCALE, 10) }\n            case 100000000000000000000000000000 { result := mul(SCALE, 11) }\n            case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\n            case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\n            case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\n            case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\n            case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\n            case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\n            case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\n            case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\n            case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\n            case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\n            case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\n            case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\n            case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\n            case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\n            case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\n            case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\n            case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\n            case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\n            case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\n            case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\n            case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\n            case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\n            case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\n            case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\n            case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\n            case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\n            case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\n            case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\n            case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\n            case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\n            case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\n            case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\n            case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\n            case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\n            case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\n            case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\n            case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\n            case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\n            case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\n            case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\n            case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\n            case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\n            case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\n            case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\n            case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\n            case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\n            case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\n            case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\n            default {\n                result := MAX_UD60x18\n            }\n        }\n\n        if (result == MAX_UD60x18) {\n            // Do the fixed-point division inline to save gas. The denominator is log2(10).\n            unchecked {\n                result = (log2(x) * SCALE) / 3_321928094887362347;\n            }\n        }\n    }\n\n    /// @notice Calculates the binary logarithm of x.\n    ///\n    /// @dev Based on the iterative approximation algorithm.\n    /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\n    ///\n    /// Requirements:\n    /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\n    ///\n    /// Caveats:\n    /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\n    ///\n    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\n    /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\n    function log2(uint256 x) internal pure returns (uint256 result) {\n        if (x < SCALE) {\n            revert PRBMathUD60x18__LogInputTooSmall(x);\n        }\n        unchecked {\n            // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\n            uint256 n = PRBMath.mostSignificantBit(x / SCALE);\n\n            // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\n            // because n is maximum 255 and SCALE is 1e18.\n            result = n * SCALE;\n\n            // This is y = x * 2^(-n).\n            uint256 y = x >> n;\n\n            // If y = 1, the fractional part is zero.\n            if (y == SCALE) {\n                return result;\n            }\n\n            // Calculate the fractional part via the iterative approximation.\n            // The \"delta >>= 1\" part is equivalent to \"delta /= 2\", but shifting bits is faster.\n            for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\n                y = (y * y) / SCALE;\n\n                // Is y^2 > 2 and so in the range [2,4)?\n                if (y >= 2 * SCALE) {\n                    // Add the 2^(-m) factor to the logarithm.\n                    result += delta;\n\n                    // Corresponds to z/2 on Wikipedia.\n                    y >>= 1;\n                }\n            }\n        }\n    }\n\n    /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\n    /// fixed-point number.\n    /// @dev See the documentation for the \"PRBMath.mulDivFixedPoint\" function.\n    /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n    /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n    /// @return result The product as an unsigned 60.18-decimal fixed-point number.\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\n        result = PRBMath.mulDivFixedPoint(x, y);\n    }\n\n    /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\n    function pi() internal pure returns (uint256 result) {\n        result = 3_141592653589793238;\n    }\n\n    /// @notice Raises x to the power of y.\n    ///\n    /// @dev Based on the insight that x^y = 2^(log2(x) * y).\n    ///\n    /// Requirements:\n    /// - All from \"exp2\", \"log2\" and \"mul\".\n    ///\n    /// Caveats:\n    /// - All from \"exp2\", \"log2\" and \"mul\".\n    /// - Assumes 0^0 is 1.\n    ///\n    /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\n    /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\n    /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\n    function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\n        if (x == 0) {\n            result = y == 0 ? SCALE : uint256(0);\n        } else {\n            result = exp2(mul(log2(x), y));\n        }\n    }\n\n    /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\n    /// famous algorithm \"exponentiation by squaring\".\n    ///\n    /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\n    ///\n    /// Requirements:\n    /// - The result must fit within MAX_UD60x18.\n    ///\n    /// Caveats:\n    /// - All from \"mul\".\n    /// - Assumes 0^0 is 1.\n    ///\n    /// @param x The base as an unsigned 60.18-decimal fixed-point number.\n    /// @param y The exponent as an uint256.\n    /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n    function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\n        // Calculate the first iteration of the loop in advance.\n        result = y & 1 > 0 ? x : SCALE;\n\n        // Equivalent to \"for(y /= 2; y > 0; y /= 2)\" but faster.\n        for (y >>= 1; y > 0; y >>= 1) {\n            x = PRBMath.mulDivFixedPoint(x, x);\n\n            // Equivalent to \"y % 2 == 1\" but faster.\n            if (y & 1 > 0) {\n                result = PRBMath.mulDivFixedPoint(result, x);\n            }\n        }\n    }\n\n    /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\n    function scale() internal pure returns (uint256 result) {\n        result = SCALE;\n    }\n\n    /// @notice Calculates the square root of x, rounding down.\n    /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n    ///\n    /// Requirements:\n    /// - x must be less than MAX_UD60x18 / SCALE.\n    ///\n    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\n    /// @return result The result as an unsigned 60.18-decimal fixed-point .\n    function sqrt(uint256 x) internal pure returns (uint256 result) {\n        unchecked {\n            if (x > MAX_UD60x18 / SCALE) {\n                revert PRBMathUD60x18__SqrtOverflow(x);\n            }\n            // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\n            // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\n            result = PRBMath.sqrt(x * SCALE);\n        }\n    }\n\n    /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\n    /// @param x The unsigned 60.18-decimal fixed-point number to convert.\n    /// @return result The same number in basic integer form.\n    function toUint(uint256 x) internal pure returns (uint256 result) {\n        unchecked {\n            result = x / SCALE;\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 100000
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}