creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/StrategyCurveBoostedFactoryClonable.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity 0.8.19;\n\nimport {Math} from \"@openzeppelin/contracts@4.9.3/utils/math/Math.sol\";\nimport \"github.com/yearn/yearn-vaults/blob/v0.4.6/contracts/BaseStrategy.sol\";\nimport \"./interfaces/CurveInterfaces.sol\";\n\ncontract StrategyCurveBoostedFactoryClonable is BaseStrategy {\n    using SafeERC20 for IERC20;\n\n    /* ========== STATE VARIABLES ========== */\n\n    /// @notice Yearns strategyProxy, needed for interacting with our Curve Voter.\n    ICurveStrategyProxy public proxy;\n\n    /// @notice Curve gauge contract, most are tokenized, held by Yearns voter.\n    address public gauge;\n\n    /// @notice The percentage of CRV from each harvest that we send to our voter (out of 10,000).\n    uint256 public localKeepCRV;\n\n    /// @notice The address of our Curve voter. This is where we send any keepCRV.\n    address public curveVoter;\n\n    // this means all of our fee values are in basis points\n    uint256 internal constant FEE_DENOMINATOR = 10000;\n\n    /// @notice The address of our base token (CRV for Curve, BAL for Balancer, etc.).\n    IERC20 public constant crv =\n        IERC20(0xD533a949740bb3306d119CC777fa900bA034cd52);\n\n    // ySwaps stuff\n    /// @notice The address of our ySwaps trade factory.\n    address public tradeFactory;\n\n    /// @notice Array of any extra rewards tokens this Convex pool may have.\n    address[] public rewardsTokens;\n\n    /// @notice Will only be true on the original deployed contract and not on clones; we dont want to clone a clone.\n    bool public isOriginal = true;\n\n    /// @notice Used to track the deployed version of this contract. Maps to releases in the CurveVaultFactory repo.\n    string public constant strategyVersion = \"4.0.0\";\n\n    /* ========== CONSTRUCTOR ========== */\n\n    constructor(\n        address _vault,\n        address _tradeFactory,\n        address _proxy,\n        address _gauge\n    ) BaseStrategy(_vault) {\n        _initializeStrat(_tradeFactory, _proxy, _gauge);\n    }\n\n    /* ========== CLONING ========== */\n\n    event Cloned(address indexed clone);\n\n    /**\n     * @notice Use this to clone an exact copy of this strategy on another vault.\n     * @dev In practice, this will only be called by the factory on the template contract.\n     * @param _vault Vault address we are targeting with this strategy.\n     * @param _strategist Address to grant the strategist role.\n     * @param _rewards If we have any strategist rewards, send them here.\n     * @param _keeper Address to grant the keeper role.\n     * @param _tradeFactory Our trade factory address.\n     * @param _proxy Our strategy proxy address.\n     * @param _gauge Gauge address for this strategy.\n     * @return newStrategy Address of our new cloned strategy.\n     */\n    function cloneStrategyCurveBoosted(\n        address _vault,\n        address _strategist,\n        address _rewards,\n        address _keeper,\n        address _tradeFactory,\n        address _proxy,\n        address _gauge\n    ) external returns (address newStrategy) {\n        // dont clone a clone\n        if (!isOriginal) {\n            revert(\"Cant clone a clone\");\n        }\n\n        // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol\n        bytes20 addressBytes = bytes20(address(this));\n        assembly {\n            // EIP-1167 bytecode\n            let clone_code := mload(0x40)\n            mstore(\n                clone_code,\n                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000\n            )\n            mstore(add(clone_code, 0x14), addressBytes)\n            mstore(\n                add(clone_code, 0x28),\n                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000\n            )\n            newStrategy := create(0, clone_code, 0x37)\n        }\n\n        StrategyCurveBoostedFactoryClonable(newStrategy).initialize(\n            _vault,\n            _strategist,\n            _rewards,\n            _keeper,\n            _tradeFactory,\n            _proxy,\n            _gauge\n        );\n\n        emit Cloned(newStrategy);\n    }\n\n    /**\n     * @notice Initialize the strategy.\n     * @dev This should only be called by the clone function above.\n     * @param _vault Vault address we are targeting with this strategy.\n     * @param _strategist Address to grant the strategist role.\n     * @param _rewards If we have any strategist rewards, send them here.\n     * @param _keeper Address to grant the keeper role.\n     * @param _tradeFactory Our trade factory address.\n     * @param _proxy Our strategy proxy address.\n     * @param _gauge Gauge address for this strategy.\n     */\n    function initialize(\n        address _vault,\n        address _strategist,\n        address _rewards,\n        address _keeper,\n        address _tradeFactory,\n        address _proxy,\n        address _gauge\n    ) public {\n        _initialize(_vault, _strategist, _rewards, _keeper);\n        _initializeStrat(_tradeFactory, _proxy, _gauge);\n    }\n\n    // this is called by our original strategy, as well as any clones\n    function _initializeStrat(\n        address _tradeFactory,\n        address _proxy,\n        address _gauge\n    ) internal {\n        // make sure that we havent initialized this before\n        if (gauge != address(0)) {\n            revert(\"Already initialized\");\n        }\n\n        // 1:1 assignments\n        tradeFactory = _tradeFactory;\n        proxy = ICurveStrategyProxy(_proxy);\n        gauge = _gauge;\n\n        // want = Curve LP\n        want.approve(_proxy, type(uint256).max);\n\n        // set up our baseStrategy vars\n        minReportDelay = 3650 days;\n        maxReportDelay = 36500 days;\n        creditThreshold = 50_000e18;\n\n        // ySwaps setup\n        _setUpTradeFactory();\n    }\n\n    /* ========== VIEWS ========== */\n\n    /// @notice Strategy name.\n    function name() external view override returns (string memory) {\n        return\n            string(\n                abi.encodePacked(\n                    \"StrategyCurveBoostedFactory-\",\n                    IDetails(address(want)).symbol()\n                )\n            );\n    }\n\n    /// @notice Balance of want staked in Curves gauge.\n    function stakedBalance() public view returns (uint256) {\n        return proxy.balanceOf(gauge);\n    }\n\n    /// @notice Balance of want sitting in our strategy.\n    function balanceOfWant() public view returns (uint256) {\n        return want.balanceOf(address(this));\n    }\n\n    /// @notice Total assets the strategy holds, sum of loose and staked want.\n    function estimatedTotalAssets() public view override returns (uint256) {\n        return balanceOfWant() + stakedBalance();\n    }\n\n    /* ========== CORE STRATEGY FUNCTIONS ========== */\n\n    function prepareReturn(\n        uint256 _debtOutstanding\n    )\n        internal\n        override\n        returns (uint256 _profit, uint256 _loss, uint256 _debtPayment)\n    {\n        // rewards will be converted later with mev protection by yswaps (tradeFactory)\n        // if we have anything in the gauge, then harvest CRV from the gauge\n        uint256 _stakedBal = stakedBalance();\n        if (_stakedBal > 0) {\n            proxy.harvest(gauge);\n\n            // by default this is zero, but if we want any for our voter this will be used\n            uint256 _localKeepCRV = localKeepCRV;\n            address _curveVoter = curveVoter;\n            if (_localKeepCRV > 0 && _curveVoter != address(0)) {\n                uint256 crvBalance = crv.balanceOf(address(this));\n                uint256 _sendToVoter;\n                unchecked {\n                    _sendToVoter =\n                        (crvBalance * _localKeepCRV) /\n                        FEE_DENOMINATOR;\n                }\n                if (_sendToVoter > 0) {\n                    crv.safeTransfer(_curveVoter, _sendToVoter);\n                }\n            }\n        }\n\n        // claim any extra rewards we may have\n        if (rewardsTokens.length > 0) {\n            proxy.claimManyRewards(gauge, rewardsTokens);\n        }\n\n        // serious loss should never happen, but if it does (for instance, if Curve is hacked), lets record it accurately\n        uint256 assets = estimatedTotalAssets();\n        uint256 debt = vault.strategies(address(this)).totalDebt;\n\n        // if assets are greater than debt, things are working great!\n        if (assets >= debt) {\n            unchecked {\n                _profit = assets - debt;\n            }\n            _debtPayment = _debtOutstanding;\n\n            uint256 toFree = _profit + _debtPayment;\n\n            // freed is math.min(wantBalance, toFree)\n            (uint256 freed, ) = liquidatePosition(toFree);\n\n            if (toFree > freed) {\n                if (_debtPayment > freed) {\n                    _debtPayment = freed;\n                    _profit = 0;\n                } else {\n                    unchecked {\n                        _profit = freed - _debtPayment;\n                    }\n                }\n            }\n        }\n        // if assets are less than debt, we are in trouble. dont worry about withdrawing here, just report losses\n        else {\n            unchecked {\n                _loss = debt - assets;\n            }\n        }\n    }\n\n    function adjustPosition(uint256 _debtOutstanding) internal override {\n        // if in emergency exit, we dont want to deploy any more funds\n        if (emergencyExit) {\n            return;\n        }\n\n        // Send all of our LP tokens to the proxy and deposit to the gauge\n        uint256 _toInvest = balanceOfWant();\n        if (_toInvest > 0) {\n            want.safeTransfer(address(proxy), _toInvest);\n            proxy.deposit(gauge, address(want));\n        }\n    }\n\n    function liquidatePosition(\n        uint256 _amountNeeded\n    ) internal override returns (uint256 _liquidatedAmount, uint256 _loss) {\n        // check our loose want\n        uint256 _wantBal = balanceOfWant();\n        if (_amountNeeded > _wantBal) {\n            uint256 _stakedBal = stakedBalance();\n            if (_stakedBal > 0) {\n                uint256 _neededFromStaked;\n                unchecked {\n                    _neededFromStaked = _amountNeeded - _wantBal;\n                }\n                // withdraw whatever extra funds we need\n                proxy.withdraw(\n                    gauge,\n                    address(want),\n                    Math.min(_stakedBal, _neededFromStaked)\n                );\n            }\n            uint256 _withdrawnBal = balanceOfWant();\n            _liquidatedAmount = Math.min(_amountNeeded, _withdrawnBal);\n            unchecked {\n                _loss = _amountNeeded - _liquidatedAmount;\n            }\n        } else {\n            // we have enough balance to cover the liquidation available\n            return (_amountNeeded, 0);\n        }\n    }\n\n    // fire sale, get rid of it all!\n    function liquidateAllPositions() internal override returns (uint256) {\n        uint256 _stakedBal = stakedBalance();\n        if (_stakedBal > 0) {\n            // dont bother withdrawing zero, save gas where we can\n            proxy.withdraw(gauge, address(want), _stakedBal);\n        }\n        return balanceOfWant();\n    }\n\n    // migrate our want token to a new strategy if needed, as well as our CRV\n    function prepareMigration(address _newStrategy) internal override {\n        uint256 stakedBal = stakedBalance();\n        if (stakedBal > 0) {\n            proxy.withdraw(gauge, address(want), stakedBal);\n        }\n        uint256 crvBal = crv.balanceOf(address(this));\n\n        if (crvBal > 0) {\n            crv.safeTransfer(_newStrategy, crvBal);\n        }\n    }\n\n    // want is blocked by default, add any other tokens to protect from gov here.\n    function protectedTokens()\n        internal\n        view\n        override\n        returns (address[] memory)\n    {}\n\n    /* ========== YSWAPS ========== */\n\n    /**\n     * @notice Use to add or update rewards, rebuilds tradefactory too\n     * @dev Do this before updating trade factory if we have extra rewards. Can only be called by governance.\n     * @param _rewards Rewards tokens to add to our trade factory.\n     */\n    function updateRewards(address[] memory _rewards) external onlyGovernance {\n        address tf = tradeFactory;\n        _removeTradeFactoryPermissions(true);\n        rewardsTokens = _rewards;\n\n        tradeFactory = tf;\n        _setUpTradeFactory();\n    }\n\n    /**\n     * @notice Use to update our trade factory.\n     * @dev Can only be called by governance.\n     * @param _newTradeFactory Address of new trade factory.\n     */\n    function updateTradeFactory(\n        address _newTradeFactory\n    ) external onlyGovernance {\n        require(\n            _newTradeFactory != address(0),\n            \"Cant remove with this function\"\n        );\n        _removeTradeFactoryPermissions(true);\n        tradeFactory = _newTradeFactory;\n        _setUpTradeFactory();\n    }\n\n    function _setUpTradeFactory() internal {\n        // approve and set up trade factory\n        address _tradeFactory = tradeFactory;\n        address _want = address(want);\n\n        ITradeFactory tf = ITradeFactory(_tradeFactory);\n        crv.approve(_tradeFactory, type(uint256).max);\n        tf.enable(address(crv), _want);\n\n        // enable for all rewards tokens too\n        for (uint256 i; i < rewardsTokens.length; ++i) {\n            address _rewardsToken = rewardsTokens[i];\n            IERC20(_rewardsToken).approve(_tradeFactory, type(uint256).max);\n            tf.enable(_rewardsToken, _want);\n        }\n    }\n\n    /**\n     * @notice Use this to remove permissions from our current trade factory.\n     * @dev Once this is called, setUpTradeFactory must be called to get things working again.\n     * @param _disableTf Specify whether to disable the tradefactory when removing. Option given in case we need to get\n     *  around a reverting disable.\n     */\n    function removeTradeFactoryPermissions(\n        bool _disableTf\n    ) external onlyVaultManagers {\n        _removeTradeFactoryPermissions(_disableTf);\n    }\n\n    function _removeTradeFactoryPermissions(bool _disableTf) internal {\n        address _tradeFactory = tradeFactory;\n        if (_tradeFactory == address(0)) {\n            return;\n        }\n        ITradeFactory tf = ITradeFactory(_tradeFactory);\n\n        address _want = address(want);\n        crv.approve(_tradeFactory, 0);\n        if (_disableTf) {\n            tf.disable(address(crv), _want);\n        }\n\n        // disable for all rewards tokens too\n        for (uint256 i; i < rewardsTokens.length; ++i) {\n            address _rewardsToken = rewardsTokens[i];\n            IERC20(_rewardsToken).approve(_tradeFactory, 0);\n            if (_disableTf) {\n                tf.disable(_rewardsToken, _want);\n            }\n        }\n\n        tradeFactory = address(0);\n    }\n\n    /* ========== KEEP3RS ========== */\n\n    /**\n     * @notice\n     *  Provide a signal to the keeper that harvest() should be called.\n     *\n     *  Dont harvest if a strategy is inactive.\n     *  If we exceed our max delay, then harvest no matter what. For\n     *  our min delay, credit threshold, and manual force trigger,\n     *  only harvest if our gas price is acceptable.\n     *\n     * @param callCostinEth The keepers estimated gas cost to call harvest() (in wei).\n     * @return True if harvest() should be called, false otherwise.\n     */\n    function harvestTrigger(\n        uint256 callCostinEth\n    ) public view override returns (bool) {\n        // Should not trigger if strategy is not active (no assets and no debtRatio). This means we dont need to adjust keeper job.\n        if (!isActive()) {\n            return false;\n        }\n\n        StrategyParams memory params = vault.strategies(address(this));\n        // harvest no matter what once we reach our maxDelay\n        if (block.timestamp - params.lastReport > maxReportDelay) {\n            return true;\n        }\n\n        // check if the base fee gas price is higher than we allow. if it is, block harvests.\n        if (!isBaseFeeAcceptable()) {\n            return false;\n        }\n\n        // trigger if we want to manually harvest, but only if our gas price is acceptable\n        if (forceHarvestTriggerOnce) {\n            return true;\n        }\n\n        // harvest if we hit our minDelay, but only if our gas price is acceptable\n        if (block.timestamp - params.lastReport > minReportDelay) {\n            return true;\n        }\n\n        // harvest our credit if its above our threshold\n        if (vault.creditAvailable() > creditThreshold) {\n            return true;\n        }\n\n        // otherwise, we dont harvest\n        return false;\n    }\n\n    /**\n     * @notice Convert our keepers eth cost into want\n     * @dev We dont use this since we dont factor call cost into our harvestTrigger.\n     * @param _ethAmount Amount of ether spent.\n     * @return Value of ether in want.\n     */\n    function ethToWant(\n        uint256 _ethAmount\n    ) public view override returns (uint256) {}\n\n    /* ========== SETTERS ========== */\n    // These functions are useful for setting parameters of the strategy that may need to be adjusted.\n\n    /**\n     * @notice Use this to set or update our keep amounts for this strategy.\n     * @dev Must be less than 10,000. Set in basis points. Only governance can set this.\n     * @param _keepCrv Percent of each CRV harvest to send to our voter.\n     */\n    function setLocalKeepCrv(uint256 _keepCrv) external onlyGovernance {\n        if (_keepCrv > 10_000) {\n            revert();\n        }\n        if (_keepCrv > 0 && curveVoter == address(0)) {\n            revert(\"Set voter when keep >0\");\n        }\n        localKeepCRV = _keepCrv;\n    }\n\n    /**\n     * @notice Use this to set or update our voter contracts.\n     * @dev For Curve strategies, this is where we send our keepCRV. Only governance can set this.\n     * @param _curveVoter Address of our curve voter.\n     */\n    function setVoter(address _curveVoter) external onlyGovernance {\n        curveVoter = _curveVoter;\n    }\n\n    /**\n     * @notice Use this to set or update our strategy proxy.\n     * @dev Only governance can set this.\n     * @param _strategyProxy Address of our curve strategy proxy.\n     */\n    function setProxy(address _strategyProxy) external onlyGovernance {\n        proxy = ICurveStrategyProxy(_strategyProxy);\n    }\n}\n"
      },
      "contracts/interfaces/CurveInterfaces.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.15;\n\ninterface ICurveStrategyProxy {\n    function balanceOf(address _gauge) external view returns (uint256);\n\n    function harvest(address _gauge) external;\n\n    function claimManyRewards(address _gauge, address[] memory _token) external;\n\n    function deposit(address _gauge, address _token) external;\n\n    function withdraw(\n        address _gauge,\n        address _token,\n        uint256 _amount\n    ) external returns (uint256);\n}\n\ninterface ITradeFactory {\n    function enable(address, address) external;\n\n    function disable(address, address) external;\n}\n\ninterface IDetails {\n    // get details from curve\n    function name() external view returns (string memory);\n\n    function symbol() external view returns (string memory);\n}\n"
      },
      "github.com/yearn/yearn-vaults/blob/v0.4.6/contracts/BaseStrategy.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.8.15;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nstruct StrategyParams {\n    uint256 performanceFee;\n    uint256 activation;\n    uint256 debtRatio;\n    uint256 minDebtPerHarvest;\n    uint256 maxDebtPerHarvest;\n    uint256 lastReport;\n    uint256 totalDebt;\n    uint256 totalGain;\n    uint256 totalLoss;\n}\n\ninterface VaultAPI is IERC20 {\n    function name() external view returns (string calldata);\n\n    function symbol() external view returns (string calldata);\n\n    function decimals() external view returns (uint256);\n\n    function apiVersion() external pure returns (string memory);\n\n    function permit(\n        address owner,\n        address spender,\n        uint256 amount,\n        uint256 expiry,\n        bytes calldata signature\n    ) external returns (bool);\n\n    // NOTE: Vyper produces multiple signatures for a given function with \"default\" args\n    function deposit() external returns (uint256);\n\n    function deposit(uint256 amount) external returns (uint256);\n\n    function deposit(uint256 amount, address recipient) external returns (uint256);\n\n    // NOTE: Vyper produces multiple signatures for a given function with \"default\" args\n    function withdraw() external returns (uint256);\n\n    function withdraw(uint256 maxShares) external returns (uint256);\n\n    function withdraw(uint256 maxShares, address recipient) external returns (uint256);\n\n    function token() external view returns (address);\n\n    function strategies(address _strategy) external view returns (StrategyParams memory);\n\n    function pricePerShare() external view returns (uint256);\n\n    function totalAssets() external view returns (uint256);\n\n    function depositLimit() external view returns (uint256);\n\n    function maxAvailableShares() external view returns (uint256);\n\n    /**\n     * View how much the Vault would increase this Strategy's borrow limit,\n     * based on its present performance (since its last report). Can be used to\n     * determine expectedReturn in your Strategy.\n     */\n    function creditAvailable() external view returns (uint256);\n\n    /**\n     * View how much the Vault would like to pull back from the Strategy,\n     * based on its present performance (since its last report). Can be used to\n     * determine expectedReturn in your Strategy.\n     */\n    function debtOutstanding() external view returns (uint256);\n\n    /**\n     * View how much the Vault expect this Strategy to return at the current\n     * block, based on its present performance (since its last report). Can be\n     * used to determine expectedReturn in your Strategy.\n     */\n    function expectedReturn() external view returns (uint256);\n\n    /**\n     * This is the main contact point where the Strategy interacts with the\n     * Vault. It is critical that this call is handled as intended by the\n     * Strategy. Therefore, this function will be called by BaseStrategy to\n     * make sure the integration is correct.\n     */\n    function report(\n        uint256 _gain,\n        uint256 _loss,\n        uint256 _debtPayment\n    ) external returns (uint256);\n\n    /**\n     * This function should only be used in the scenario where the Strategy is\n     * being retired but no migration of the positions are possible, or in the\n     * extreme scenario that the Strategy needs to be put into \"Emergency Exit\"\n     * mode in order for it to exit as quickly as possible. The latter scenario\n     * could be for any reason that is considered \"critical\" that the Strategy\n     * exits its position as fast as possible, such as a sudden change in\n     * market conditions leading to losses, or an imminent failure in an\n     * external dependency.\n     */\n    function revokeStrategy() external;\n\n    /**\n     * View the governance address of the Vault to assert privileged functions\n     * can only be called by governance. The Strategy serves the Vault, so it\n     * is subject to governance defined by the Vault.\n     */\n    function governance() external view returns (address);\n\n    /**\n     * View the management address of the Vault to assert privileged functions\n     * can only be called by management. The Strategy serves the Vault, so it\n     * is subject to management defined by the Vault.\n     */\n    function management() external view returns (address);\n\n    /**\n     * View the guardian address of the Vault to assert privileged functions\n     * can only be called by guardian. The Strategy serves the Vault, so it\n     * is subject to guardian defined by the Vault.\n     */\n    function guardian() external view returns (address);\n}\n\n/**\n * This interface is here for the keeper bot to use.\n */\ninterface StrategyAPI {\n    function name() external view returns (string memory);\n\n    function vault() external view returns (address);\n\n    function want() external view returns (address);\n\n    function apiVersion() external pure returns (string memory);\n\n    function keeper() external view returns (address);\n\n    function isActive() external view returns (bool);\n\n    function delegatedAssets() external view returns (uint256);\n\n    function estimatedTotalAssets() external view returns (uint256);\n\n    function tendTrigger(uint256 callCost) external view returns (bool);\n\n    function tend() external;\n\n    function harvestTrigger(uint256 callCost) external view returns (bool);\n\n    function harvest() external;\n\n    event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);\n}\n\ninterface HealthCheck {\n    function check(\n        uint256 profit,\n        uint256 loss,\n        uint256 debtPayment,\n        uint256 debtOutstanding,\n        uint256 totalDebt\n    ) external view returns (bool);\n}\n\ninterface IBaseFee {\n    function isCurrentBaseFeeAcceptable() external view returns (bool);\n}\n\n/**\n * @title Yearn Base Strategy\n * @author yearn.finance\n * @notice\n *  BaseStrategy implements all of the required functionality to interoperate\n *  closely with the Vault contract. This contract should be inherited and the\n *  abstract methods implemented to adapt the Strategy to the particular needs\n *  it has to create a return.\n *\n *  Of special interest is the relationship between `harvest()` and\n *  `vault.report()'. `harvest()` may be called simply because enough time has\n *  elapsed since the last report, and not because any funds need to be moved\n *  or positions adjusted. This is critical so that the Vault may maintain an\n *  accurate picture of the Strategy's performance. See  `vault.report()`,\n *  `harvest()`, and `harvestTrigger()` for further details.\n */\n\nabstract contract BaseStrategy {\n    using SafeERC20 for IERC20;\n    string public metadataURI;\n\n    // health checks\n    bool public doHealthCheck;\n    address public healthCheck;\n\n    /**\n     * @notice\n     *  Used to track which version of `StrategyAPI` this Strategy\n     *  implements.\n     * @dev The Strategy's version must match the Vault's `API_VERSION`.\n     * @return A string which holds the current API version of this contract.\n     */\n    function apiVersion() public pure returns (string memory) {\n        return \"0.4.6\";\n    }\n\n    /**\n     * @notice This Strategy's name.\n     * @dev\n     *  You can use this field to manage the \"version\" of this Strategy, e.g.\n     *  `StrategySomethingOrOtherV1`. However, \"API Version\" is managed by\n     *  `apiVersion()` function above.\n     * @return This Strategy's name.\n     */\n    function name() external view virtual returns (string memory);\n\n    /**\n     * @notice\n     *  The amount (priced in want) of the total assets managed by this strategy should not count\n     *  towards Yearn's TVL calculations.\n     * @dev\n     *  You can override this field to set it to a non-zero value if some of the assets of this\n     *  Strategy is somehow delegated inside another part of of Yearn's ecosystem e.g. another Vault.\n     *  Note that this value must be strictly less than or equal to the amount provided by\n     *  `estimatedTotalAssets()` below, as the TVL calc will be total assets minus delegated assets.\n     *  Also note that this value is used to determine the total assets under management by this\n     *  strategy, for the purposes of computing the management fee in `Vault`\n     * @return\n     *  The amount of assets this strategy manages that should not be included in Yearn's Total Value\n     *  Locked (TVL) calculation across it's ecosystem.\n     */\n    function delegatedAssets() external view virtual returns (uint256) {\n        return 0;\n    }\n\n    VaultAPI public vault;\n    address public strategist;\n    address public rewards;\n    address public keeper;\n\n    IERC20 public want;\n\n    // So indexers can keep track of this\n    event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);\n\n    event UpdatedStrategist(address newStrategist);\n\n    event UpdatedKeeper(address newKeeper);\n\n    event UpdatedRewards(address rewards);\n\n    event UpdatedMinReportDelay(uint256 delay);\n\n    event UpdatedMaxReportDelay(uint256 delay);\n\n    event UpdatedBaseFeeOracle(address baseFeeOracle);\n\n    event UpdatedCreditThreshold(uint256 creditThreshold);\n\n    event ForcedHarvestTrigger(bool triggerState);\n\n    event EmergencyExitEnabled();\n\n    event UpdatedMetadataURI(string metadataURI);\n\n    event SetHealthCheck(address);\n    event SetDoHealthCheck(bool);\n\n    // The minimum number of seconds between harvest calls. See\n    // `setMinReportDelay()` for more details.\n    uint256 public minReportDelay;\n\n    // The maximum number of seconds between harvest calls. See\n    // `setMaxReportDelay()` for more details.\n    uint256 public maxReportDelay;\n\n    // See note on `setEmergencyExit()`.\n    bool public emergencyExit;\n\n    // See note on `isBaseFeeOracleAcceptable()`.\n    address public baseFeeOracle;\n\n    // See note on `setCreditThreshold()`\n    uint256 public creditThreshold;\n\n    // See note on `setForceHarvestTriggerOnce`\n    bool public forceHarvestTriggerOnce;\n\n    // modifiers\n    modifier onlyAuthorized() {\n        _onlyAuthorized();\n        _;\n    }\n\n    modifier onlyEmergencyAuthorized() {\n        _onlyEmergencyAuthorized();\n        _;\n    }\n\n    modifier onlyStrategist() {\n        _onlyStrategist();\n        _;\n    }\n\n    modifier onlyGovernance() {\n        _onlyGovernance();\n        _;\n    }\n\n    modifier onlyRewarder() {\n        _onlyRewarder();\n        _;\n    }\n\n    modifier onlyKeepers() {\n        _onlyKeepers();\n        _;\n    }\n\n    modifier onlyVaultManagers() {\n        _onlyVaultManagers();\n        _;\n    }\n\n    function _onlyAuthorized() internal {\n        require(msg.sender == strategist || msg.sender == governance());\n    }\n\n    function _onlyEmergencyAuthorized() internal {\n        require(msg.sender == strategist || msg.sender == governance() || msg.sender == vault.guardian() || msg.sender == vault.management());\n    }\n\n    function _onlyStrategist() internal {\n        require(msg.sender == strategist);\n    }\n\n    function _onlyGovernance() internal {\n        require(msg.sender == governance());\n    }\n\n    function _onlyRewarder() internal {\n        require(msg.sender == governance() || msg.sender == strategist);\n    }\n\n    function _onlyKeepers() internal {\n        require(\n            msg.sender == keeper ||\n                msg.sender == strategist ||\n                msg.sender == governance() ||\n                msg.sender == vault.guardian() ||\n                msg.sender == vault.management()\n        );\n    }\n\n    function _onlyVaultManagers() internal {\n        require(msg.sender == vault.management() || msg.sender == governance());\n    }\n\n    constructor(address _vault) {\n        _initialize(_vault, msg.sender, msg.sender, msg.sender);\n    }\n\n    /**\n     * @notice\n     *  Initializes the Strategy, this is called only once, when the\n     *  contract is deployed.\n     * @dev `_vault` should implement `VaultAPI`.\n     * @param _vault The address of the Vault responsible for this Strategy.\n     * @param _strategist The address to assign as `strategist`.\n     * The strategist is able to change the reward address\n     * @param _rewards  The address to use for pulling rewards.\n     * @param _keeper The adddress of the _keeper. _keeper\n     * can harvest and tend a strategy.\n     */\n    function _initialize(\n        address _vault,\n        address _strategist,\n        address _rewards,\n        address _keeper\n    ) internal {\n        require(address(want) == address(0), \"Strategy already initialized\");\n\n        vault = VaultAPI(_vault);\n        want = IERC20(vault.token());\n        want.safeApprove(_vault, type(uint256).max); // Give Vault unlimited access (might save gas)\n        strategist = _strategist;\n        rewards = _rewards;\n        keeper = _keeper;\n\n        // initialize variables\n        maxReportDelay = 30 days;\n        creditThreshold = 1_000_000 * 10**vault.decimals(); // set this high by default so we don't get tons of false triggers if not changed\n\n        vault.approve(rewards, type(uint256).max); // Allow rewards to be pulled\n    }\n\n    function setHealthCheck(address _healthCheck) external onlyVaultManagers {\n        emit SetHealthCheck(_healthCheck);\n        healthCheck = _healthCheck;\n    }\n\n    function setDoHealthCheck(bool _doHealthCheck) external onlyVaultManagers {\n        emit SetDoHealthCheck(_doHealthCheck);\n        doHealthCheck = _doHealthCheck;\n    }\n\n    /**\n     * @notice\n     *  Used to change `strategist`.\n     *\n     *  This may only be called by governance or the existing strategist.\n     * @param _strategist The new address to assign as `strategist`.\n     */\n    function setStrategist(address _strategist) external onlyAuthorized {\n        require(_strategist != address(0));\n        strategist = _strategist;\n        emit UpdatedStrategist(_strategist);\n    }\n\n    /**\n     * @notice\n     *  Used to change `keeper`.\n     *\n     *  `keeper` is the only address that may call `tend()` or `harvest()`,\n     *  other than `governance()` or `strategist`. However, unlike\n     *  `governance()` or `strategist`, `keeper` may *only* call `tend()`\n     *  and `harvest()`, and no other authorized functions, following the\n     *  principle of least privilege.\n     *\n     *  This may only be called by governance or the strategist.\n     * @param _keeper The new address to assign as `keeper`.\n     */\n    function setKeeper(address _keeper) external onlyAuthorized {\n        require(_keeper != address(0));\n        keeper = _keeper;\n        emit UpdatedKeeper(_keeper);\n    }\n\n    /**\n     * @notice\n     *  Used to change `rewards`. EOA or smart contract which has the permission\n     *  to pull rewards from the vault.\n     *\n     *  This may only be called by the strategist.\n     * @param _rewards The address to use for pulling rewards.\n     */\n    function setRewards(address _rewards) external onlyRewarder {\n        require(_rewards != address(0));\n        vault.approve(rewards, 0);\n        rewards = _rewards;\n        vault.approve(rewards, type(uint256).max);\n        emit UpdatedRewards(_rewards);\n    }\n\n    /**\n     * @notice\n     *  Used to change `minReportDelay`. `minReportDelay` is the minimum number\n     *  of blocks that should pass for `harvest()` to be called.\n     *\n     *  For external keepers (such as the Keep3r network), this is the minimum\n     *  time between jobs to wait. (see `harvestTrigger()`\n     *  for more details.)\n     *\n     *  This may only be called by governance or the strategist.\n     * @param _delay The minimum number of seconds to wait between harvests.\n     */\n    function setMinReportDelay(uint256 _delay) external onlyAuthorized {\n        minReportDelay = _delay;\n        emit UpdatedMinReportDelay(_delay);\n    }\n\n    /**\n     * @notice\n     *  Used to change `maxReportDelay`. `maxReportDelay` is the maximum number\n     *  of blocks that should pass for `harvest()` to be called.\n     *\n     *  For external keepers (such as the Keep3r network), this is the maximum\n     *  time between jobs to wait. (see `harvestTrigger()`\n     *  for more details.)\n     *\n     *  This may only be called by governance or the strategist.\n     * @param _delay The maximum number of seconds to wait between harvests.\n     */\n    function setMaxReportDelay(uint256 _delay) external onlyAuthorized {\n        maxReportDelay = _delay;\n        emit UpdatedMaxReportDelay(_delay);\n    }\n\n    /**\n     * @notice\n     *  Used to ensure that any significant credit a strategy has from the\n     *  vault will be automatically harvested.\n     *\n     *  This may only be called by governance or management.\n     * @param _creditThreshold The number of want tokens that will\n     *  automatically trigger a harvest.\n     */\n    function setCreditThreshold(uint256 _creditThreshold) external onlyVaultManagers {\n        creditThreshold = _creditThreshold;\n        emit UpdatedCreditThreshold(_creditThreshold);\n    }\n\n    /**\n     * @notice\n     *  Used to automatically trigger a harvest by our keepers. Can be\n     *  useful if gas prices are too high now, and we want to harvest\n     *  later once prices have lowered.\n     *\n     *  This may only be called by governance or management.\n     * @param _forceHarvestTriggerOnce Value of true tells keepers to harvest\n     *  our strategy\n     */\n    function setForceHarvestTriggerOnce(bool _forceHarvestTriggerOnce) external onlyVaultManagers {\n        forceHarvestTriggerOnce = _forceHarvestTriggerOnce;\n        emit ForcedHarvestTrigger(_forceHarvestTriggerOnce);\n    }\n\n    /**\n     * @notice\n     *  Used to set our baseFeeOracle, which checks the network's current base\n     *  fee price to determine whether it is an optimal time to harvest or tend.\n     *\n     *  This may only be called by governance or management.\n     * @param _baseFeeOracle Address of our baseFeeOracle\n     */\n    function setBaseFeeOracle(address _baseFeeOracle) external onlyVaultManagers {\n        baseFeeOracle = _baseFeeOracle;\n        emit UpdatedBaseFeeOracle(_baseFeeOracle);\n    }\n\n    /**\n     * @notice\n     *  Used to change `metadataURI`. `metadataURI` is used to store the URI\n     * of the file describing the strategy.\n     *\n     *  This may only be called by governance or the strategist.\n     * @param _metadataURI The URI that describe the strategy.\n     */\n    function setMetadataURI(string calldata _metadataURI) external onlyAuthorized {\n        metadataURI = _metadataURI;\n        emit UpdatedMetadataURI(_metadataURI);\n    }\n\n    /**\n     * Resolve governance address from Vault contract, used to make assertions\n     * on protected functions in the Strategy.\n     */\n    function governance() internal view returns (address) {\n        return vault.governance();\n    }\n\n    /**\n     * @notice\n     *  Provide an accurate conversion from `_amtInWei` (denominated in wei)\n     *  to `want` (using the native decimal characteristics of `want`).\n     * @dev\n     *  Care must be taken when working with decimals to assure that the conversion\n     *  is compatible. As an example:\n     *\n     *      given 1e17 wei (0.1 ETH) as input, and want is USDC (6 decimals),\n     *      with USDC/ETH = 1800, this should give back 1800000000 (180 USDC)\n     *\n     * @param _amtInWei The amount (in wei/1e-18 ETH) to convert to `want`\n     * @return The amount in `want` of `_amtInEth` converted to `want`\n     **/\n    function ethToWant(uint256 _amtInWei) public view virtual returns (uint256);\n\n    /**\n     * @notice\n     *  Provide an accurate estimate for the total amount of assets\n     *  (principle + return) that this Strategy is currently managing,\n     *  denominated in terms of `want` tokens.\n     *\n     *  This total should be \"realizable\" e.g. the total value that could\n     *  *actually* be obtained from this Strategy if it were to divest its\n     *  entire position based on current on-chain conditions.\n     * @dev\n     *  Care must be taken in using this function, since it relies on external\n     *  systems, which could be manipulated by the attacker to give an inflated\n     *  (or reduced) value produced by this function, based on current on-chain\n     *  conditions (e.g. this function is possible to influence through\n     *  flashloan attacks, oracle manipulations, or other DeFi attack\n     *  mechanisms).\n     *\n     *  It is up to governance to use this function to correctly order this\n     *  Strategy relative to its peers in the withdrawal queue to minimize\n     *  losses for the Vault based on sudden withdrawals. This value should be\n     *  higher than the total debt of the Strategy and higher than its expected\n     *  value to be \"safe\".\n     * @return The estimated total assets in this Strategy.\n     */\n    function estimatedTotalAssets() public view virtual returns (uint256);\n\n    /*\n     * @notice\n     *  Provide an indication of whether this strategy is currently \"active\"\n     *  in that it is managing an active position, or will manage a position in\n     *  the future. This should correlate to `harvest()` activity, so that Harvest\n     *  events can be tracked externally by indexing agents.\n     * @return True if the strategy is actively managing a position.\n     */\n    function isActive() public view returns (bool) {\n        return vault.strategies(address(this)).debtRatio > 0 || estimatedTotalAssets() > 0;\n    }\n\n    /**\n     * Perform any Strategy unwinding or other calls necessary to capture the\n     * \"free return\" this Strategy has generated since the last time its core\n     * position(s) were adjusted. Examples include unwrapping extra rewards.\n     * This call is only used during \"normal operation\" of a Strategy, and\n     * should be optimized to minimize losses as much as possible.\n     *\n     * This method returns any realized profits and/or realized losses\n     * incurred, and should return the total amounts of profits/losses/debt\n     * payments (in `want` tokens) for the Vault's accounting (e.g.\n     * `want.balanceOf(this) >= _debtPayment + _profit`).\n     *\n     * `_debtOutstanding` will be 0 if the Strategy is not past the configured\n     * debt limit, otherwise its value will be how far past the debt limit\n     * the Strategy is. The Strategy's debt limit is configured in the Vault.\n     *\n     * NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`.\n     *       It is okay for it to be less than `_debtOutstanding`, as that\n     *       should only used as a guide for how much is left to pay back.\n     *       Payments should be made to minimize loss from slippage, debt,\n     *       withdrawal fees, etc.\n     *\n     * See `vault.debtOutstanding()`.\n     */\n    function prepareReturn(uint256 _debtOutstanding)\n        internal\n        virtual\n        returns (\n            uint256 _profit,\n            uint256 _loss,\n            uint256 _debtPayment\n        );\n\n    /**\n     * Perform any adjustments to the core position(s) of this Strategy given\n     * what change the Vault made in the \"investable capital\" available to the\n     * Strategy. Note that all \"free capital\" in the Strategy after the report\n     * was made is available for reinvestment. Also note that this number\n     * could be 0, and you should handle that scenario accordingly.\n     *\n     * See comments regarding `_debtOutstanding` on `prepareReturn()`.\n     */\n    function adjustPosition(uint256 _debtOutstanding) internal virtual;\n\n    /**\n     * Liquidate up to `_amountNeeded` of `want` of this strategy's positions,\n     * irregardless of slippage. Any excess will be re-invested with `adjustPosition()`.\n     * This function should return the amount of `want` tokens made available by the\n     * liquidation. If there is a difference between them, `_loss` indicates whether the\n     * difference is due to a realized loss, or if there is some other sitution at play\n     * (e.g. locked funds) where the amount made available is less than what is needed.\n     *\n     * NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained\n     */\n    function liquidatePosition(uint256 _amountNeeded) internal virtual returns (uint256 _liquidatedAmount, uint256 _loss);\n\n    /**\n     * Liquidate everything and returns the amount that got freed.\n     * This function is used during emergency exit instead of `prepareReturn()` to\n     * liquidate all of the Strategy's positions back to the Vault.\n     */\n\n    function liquidateAllPositions() internal virtual returns (uint256 _amountFreed);\n\n    /**\n     * @notice\n     *  Provide a signal to the keeper that `tend()` should be called. The\n     *  keeper will provide the estimated gas cost that they would pay to call\n     *  `tend()`, and this function should use that estimate to make a\n     *  determination if calling it is \"worth it\" for the keeper. This is not\n     *  the only consideration into issuing this trigger, for example if the\n     *  position would be negatively affected if `tend()` is not called\n     *  shortly, then this can return `true` even if the keeper might be\n     *  \"at a loss\" (keepers are always reimbursed by Yearn).\n     * @dev\n     *  `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).\n     *\n     *  This call and `harvestTrigger()` should never return `true` at the same\n     *  time.\n     * @param callCostInWei The keeper's estimated gas cost to call `tend()` (in wei).\n     * @return `true` if `tend()` should be called, `false` otherwise.\n     */\n    function tendTrigger(uint256 callCostInWei) public view virtual returns (bool) {\n        // We usually don't need tend, but if there are positions that need\n        // active maintainence, overriding this function is how you would\n        // signal for that.\n        // If your implementation uses the cost of the call in want, you can\n        // use uint256 callCost = ethToWant(callCostInWei);\n        // It is highly suggested to use the baseFeeOracle here as well.\n\n        return false;\n    }\n\n    /**\n     * @notice\n     *  Adjust the Strategy's position. The purpose of tending isn't to\n     *  realize gains, but to maximize yield by reinvesting any returns.\n     *\n     *  See comments on `adjustPosition()`.\n     *\n     *  This may only be called by governance, the strategist, or the keeper.\n     */\n    function tend() external onlyKeepers {\n        // Don't take profits with this call, but adjust for better gains\n        adjustPosition(vault.debtOutstanding());\n    }\n\n    /**\n     * @notice\n     *  Provide a signal to the keeper that `harvest()` should be called. The\n     *  keeper will provide the estimated gas cost that they would pay to call\n     *  `harvest()`, and this function should use that estimate to make a\n     *  determination if calling it is \"worth it\" for the keeper. This is not\n     *  the only consideration into issuing this trigger, for example if the\n     *  position would be negatively affected if `harvest()` is not called\n     *  shortly, then this can return `true` even if the keeper might be \"at a\n     *  loss\" (keepers are always reimbursed by Yearn).\n     * @dev\n     *  `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).\n     *\n     *  This call and `tendTrigger` should never return `true` at the\n     *  same time.\n     *\n     *  See `maxReportDelay`, `creditThreshold` to adjust the\n     *  strategist-controlled parameters that will influence whether this call\n     *  returns `true` or not. These parameters will be used in conjunction\n     *  with the parameters reported to the Vault (see `params`) to determine\n     *  if calling `harvest()` is merited.\n     *\n     *  This trigger also checks the network's base fee to avoid harvesting during\n     *  times of high network congestion.\n     *\n     *  Consider use of super.harvestTrigger() in any override to build on top\n     *  of this logic instead of replacing it. For example, if using `minReportDelay`.\n     *\n     *  It is expected that an external system will check `harvestTrigger()`.\n     *  This could be a script run off a desktop or cloud bot (e.g.\n     *  https://github.com/iearn-finance/yearn-vaults/blob/main/scripts/keep.py),\n     *  or via an integration with the Keep3r network (e.g.\n     *  https://github.com/Macarse/GenericKeep3rV2/blob/master/contracts/keep3r/GenericKeep3rV2.sol).\n     * @param callCostInWei The keeper's estimated gas cost to call `harvest()` (in wei).\n     * @return `true` if `harvest()` should be called, `false` otherwise.\n     */\n    function harvestTrigger(uint256 callCostInWei) public view virtual returns (bool) {\n        // Should not trigger if strategy is not active (no assets or no debtRatio)\n        if (!isActive()) return false;\n\n        // check if the base fee gas price is higher than we allow. if it is, block harvests.\n        if (!isBaseFeeAcceptable()) return false;\n\n        // trigger if we want to manually harvest, but only if our gas price is acceptable\n        if (forceHarvestTriggerOnce) return true;\n\n        // Should trigger if hasn't been called in a while\n        StrategyParams memory params = vault.strategies(address(this));\n        if ((block.timestamp - params.lastReport) >= maxReportDelay) return true;\n\n        // harvest our credit if it's above our threshold or return false\n        return (vault.creditAvailable() > creditThreshold);\n    }\n\n    /**\n     * @notice\n     *  Check if the current network base fee is below our external target. If\n     *  not, then harvestTrigger will return false.\n     * @return `true` if `harvest()` should be allowed, `false` otherwise.\n     */\n    function isBaseFeeAcceptable() public view returns (bool) {\n        if (baseFeeOracle == address(0)) return true;\n        else return IBaseFee(baseFeeOracle).isCurrentBaseFeeAcceptable();\n    }\n\n    /**\n     * @notice\n     *  Harvests the Strategy, recognizing any profits or losses and adjusting\n     *  the Strategy's position.\n     *\n     *  In the rare case the Strategy is in emergency shutdown, this will exit\n     *  the Strategy's position.\n     *\n     *  This may only be called by governance, the strategist, or the keeper.\n     * @dev\n     *  When `harvest()` is called, the Strategy reports to the Vault (via\n     *  `vault.report()`), so in some cases `harvest()` must be called in order\n     *  to take in profits, to borrow newly available funds from the Vault, or\n     *  otherwise adjust its position. In other cases `harvest()` must be\n     *  called to report to the Vault on the Strategy's position, especially if\n     *  any losses have occurred.\n     */\n    function harvest() external onlyKeepers {\n        uint256 profit = 0;\n        uint256 loss = 0;\n        uint256 debtOutstanding = vault.debtOutstanding();\n        uint256 debtPayment = 0;\n        if (emergencyExit) {\n            // Free up as much capital as possible\n            uint256 amountFreed = liquidateAllPositions();\n            if (amountFreed < debtOutstanding) {\n                loss = debtOutstanding - amountFreed;\n            } else if (amountFreed > debtOutstanding) {\n                profit = amountFreed - debtOutstanding;\n            }\n            debtPayment = debtOutstanding - loss;\n        } else {\n            // Free up returns for Vault to pull\n            (profit, loss, debtPayment) = prepareReturn(debtOutstanding);\n        }\n\n        // we're done harvesting, so reset our trigger if we used it\n        forceHarvestTriggerOnce = false;\n        emit ForcedHarvestTrigger(false);\n\n        // Allow Vault to take up to the \"harvested\" balance of this contract,\n        // which is the amount it has earned since the last time it reported to\n        // the Vault.\n        uint256 totalDebt = vault.strategies(address(this)).totalDebt;\n        debtOutstanding = vault.report(profit, loss, debtPayment);\n\n        // Check if free returns are left, and re-invest them\n        adjustPosition(debtOutstanding);\n\n        // call healthCheck contract\n        if (doHealthCheck && healthCheck != address(0)) {\n            require(HealthCheck(healthCheck).check(profit, loss, debtPayment, debtOutstanding, totalDebt), \"!healthcheck\");\n        } else {\n            emit SetDoHealthCheck(true);\n            doHealthCheck = true;\n        }\n\n        emit Harvested(profit, loss, debtPayment, debtOutstanding);\n    }\n\n    /**\n     * @notice\n     *  Withdraws `_amountNeeded` to `vault`.\n     *\n     *  This may only be called by the Vault.\n     * @param _amountNeeded How much `want` to withdraw.\n     * @return _loss Any realized losses\n     */\n    function withdraw(uint256 _amountNeeded) external returns (uint256 _loss) {\n        require(msg.sender == address(vault), \"!vault\");\n        // Liquidate as much as possible to `want`, up to `_amountNeeded`\n        uint256 amountFreed;\n        (amountFreed, _loss) = liquidatePosition(_amountNeeded);\n        // Send it directly back (NOTE: Using `msg.sender` saves some gas here)\n        want.safeTransfer(msg.sender, amountFreed);\n        // NOTE: Reinvest anything leftover on next `tend`/`harvest`\n    }\n\n    /**\n     * Do anything necessary to prepare this Strategy for migration, such as\n     * transferring any reserve or LP tokens, CDPs, or other tokens or stores of\n     * value.\n     */\n    function prepareMigration(address _newStrategy) internal virtual;\n\n    /**\n     * @notice\n     *  Transfers all `want` from this Strategy to `_newStrategy`.\n     *\n     *  This may only be called by the Vault.\n     * @dev\n     * The new Strategy's Vault must be the same as this Strategy's Vault.\n     *  The migration process should be carefully performed to make sure all\n     * the assets are migrated to the new address, which should have never\n     * interacted with the vault before.\n     * @param _newStrategy The Strategy to migrate to.\n     */\n    function migrate(address _newStrategy) external {\n        require(msg.sender == address(vault));\n        require(BaseStrategy(_newStrategy).vault() == vault);\n        prepareMigration(_newStrategy);\n        want.safeTransfer(_newStrategy, want.balanceOf(address(this)));\n    }\n\n    /**\n     * @notice\n     *  Activates emergency exit. Once activated, the Strategy will exit its\n     *  position upon the next harvest, depositing all funds into the Vault as\n     *  quickly as is reasonable given on-chain conditions.\n     *\n     *  This may only be called by governance or the strategist.\n     * @dev\n     *  See `vault.setEmergencyShutdown()` and `harvest()` for further details.\n     */\n    function setEmergencyExit() external onlyEmergencyAuthorized {\n        emergencyExit = true;\n        if (vault.strategies(address(this)).debtRatio != 0) {\n            vault.revokeStrategy();\n        }\n\n        emit EmergencyExitEnabled();\n    }\n\n    /**\n     * Override this to add all tokens/tokenized positions this contract\n     * manages on a *persistent* basis (e.g. not just for swapping back to\n     * want ephemerally).\n     *\n     * NOTE: Do *not* include `want`, already included in `sweep` below.\n     *\n     * Example:\n     * ```\n     *    function protectedTokens() internal override view returns (address[] memory) {\n     *      address[] memory protected = new address[](3);\n     *      protected[0] = tokenA;\n     *      protected[1] = tokenB;\n     *      protected[2] = tokenC;\n     *      return protected;\n     *    }\n     * ```\n     */\n    function protectedTokens() internal view virtual returns (address[] memory);\n\n    /**\n     * @notice\n     *  Removes tokens from this Strategy that are not the type of tokens\n     *  managed by this Strategy. This may be used in case of accidentally\n     *  sending the wrong kind of token to this Strategy.\n     *\n     *  Tokens will be sent to `governance()`.\n     *\n     *  This will fail if an attempt is made to sweep `want`, or any tokens\n     *  that are protected by this Strategy.\n     *\n     *  This may only be called by governance.\n     * @dev\n     *  Implement `protectedTokens()` to specify any additional tokens that\n     *  should be protected from sweeping in addition to `want`.\n     * @param _token The token to transfer out of this vault.\n     */\n    function sweep(address _token) external onlyGovernance {\n        require(_token != address(want), \"!want\");\n        require(_token != address(vault), \"!shares\");\n\n        address[] memory _protectedTokens = protectedTokens();\n        for (uint256 i; i < _protectedTokens.length; i++) require(_token != _protectedTokens[i], \"!protected\");\n\n        IERC20(_token).safeTransfer(governance(), IERC20(_token).balanceOf(address(this)));\n    }\n}\n\nabstract contract BaseStrategyInitializable is BaseStrategy {\n    bool public isOriginal = true;\n    event Cloned(address indexed clone);\n\n    constructor(address _vault) BaseStrategy(_vault) {}\n\n    function initialize(\n        address _vault,\n        address _strategist,\n        address _rewards,\n        address _keeper\n    ) external virtual {\n        _initialize(_vault, _strategist, _rewards, _keeper);\n    }\n\n    function clone(address _vault) external returns (address) {\n        return clone(_vault, msg.sender, msg.sender, msg.sender);\n    }\n\n    function clone(\n        address _vault,\n        address _strategist,\n        address _rewards,\n        address _keeper\n    ) public returns (address newStrategy) {\n        require(isOriginal, \"!clone\");\n        // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol\n        bytes20 addressBytes = bytes20(address(this));\n\n        assembly {\n            // EIP-1167 bytecode\n            let clone_code := mload(0x40)\n            mstore(clone_code, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n            mstore(add(clone_code, 0x14), addressBytes)\n            mstore(add(clone_code, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n            newStrategy := create(0, clone_code, 0x37)\n        }\n\n        BaseStrategyInitializable(newStrategy).initialize(_vault, _strategist, _rewards, _keeper);\n\n        emit Cloned(newStrategy);\n    }\n}\n"
      },
      "@openzeppelin/contracts@4.9.3/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "@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"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "abi"
          ]
        }
      },
      "remappings": []
    }
  }}