{"file_path":"RoleManager.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: AGPL-3.0\r\npragma solidity 0.8.18;\r\n\r\ncontract Governance {\r\n    /// @notice Emitted when the governance address is updated.\r\n    event GovernanceTransferred(\r\n        address indexed previousGovernance,\r\n        address indexed newGovernance\r\n    );\r\n\r\n    modifier onlyGovernance() {\r\n        _checkGovernance();\r\n        _;\r\n    }\r\n\r\n    /// @notice Checks if the msg sender is the governance.\r\n    function _checkGovernance() internal view virtual {\r\n        require(governance == msg.sender, \"!governance\");\r\n    }\r\n\r\n    /// @notice Address that can set the default base fee and provider\r\n    address public governance;\r\n\r\n    constructor(address _governance) {\r\n        governance = _governance;\r\n\r\n        emit GovernanceTransferred(address(0), _governance);\r\n    }\r\n\r\n    /**\r\n     * @notice Sets a new address as the governance of the contract.\r\n     * @dev Throws if the caller is not current governance.\r\n     * @param _newGovernance The new governance address.\r\n     */\r\n    function transferGovernance(\r\n        address _newGovernance\r\n    ) external virtual onlyGovernance {\r\n        require(_newGovernance != address(0), \"ZERO ADDRESS\");\r\n        address oldGovernance = governance;\r\n        governance = _newGovernance;\r\n\r\n        emit GovernanceTransferred(oldGovernance, _newGovernance);\r\n    }\r\n}\r\n\r\ninterface IFactory {\r\n    function apiVersion() external view returns (string memory);\r\n}\r\n\r\n/**\r\n * @title YearnV3 Release Registry\r\n * @author yearn.finance\r\n * @notice\r\n *  Used by Yearn Governance to track on chain all\r\n *  releases of the V3 vaults by API Version.\r\n */\r\ncontract ReleaseRegistry is Governance {\r\n    event NewRelease(\r\n        uint256 indexed releaseId,\r\n        address indexed factory,\r\n        string apiVersion\r\n    );\r\n\r\n    string public constant name = \"Yearn V3 Release Registry\";\r\n\r\n    // The total number of releases that have been deployed\r\n    uint256 public numReleases;\r\n\r\n    // Mapping of release id starting at 0 to the address\r\n    // of the corresponding factory for that release.\r\n    mapping(uint256 => address) public factories;\r\n\r\n    // Mapping of the API version for a specific release to the\r\n    // place in the order it was released.\r\n    mapping(string => uint256) public releaseTargets;\r\n\r\n    constructor(address _governance) Governance(_governance) {}\r\n\r\n    /**\r\n     * @notice Returns the latest factory.\r\n     * @dev Throws if no releases are registered yet.\r\n     * @return The address of the factory for the latest release.\r\n     */\r\n    function latestFactory() external view virtual returns (address) {\r\n        return factories[numReleases - 1];\r\n    }\r\n\r\n    /**\r\n     * @notice Returns the api version of the latest release.\r\n     * @dev Throws if no releases are registered yet.\r\n     * @return The api version of the latest release.\r\n     */\r\n    function latestRelease() external view virtual returns (string memory) {\r\n        return IFactory(factories[numReleases - 1]).apiVersion(); // dev: no release\r\n    }\r\n\r\n    /**\r\n     * @notice Issue a new release using a deployed factory.\r\n     * @dev Stores the factory address in `factories` and the release\r\n     * target in `releaseTargets` with its associated API version.\r\n     *\r\n     *   Throws if caller isn't `governance`.\r\n     *   Throws if the api version is the same as the previous release.\r\n     *   Emits a `NewRelease` event.\r\n     *\r\n     * @param _factory The factory that will be used create new vaults.\r\n     */\r\n    function newRelease(address _factory) external virtual onlyGovernance {\r\n        // Check if the release is different from the current one\r\n        uint256 releaseId = numReleases;\r\n\r\n        string memory apiVersion = IFactory(_factory).apiVersion();\r\n\r\n        if (releaseId > 0) {\r\n            // Make sure this isn't the same as the last one\r\n            require(\r\n                keccak256(\r\n                    bytes(IFactory(factories[releaseId - 1]).apiVersion())\r\n                ) != keccak256(bytes(apiVersion)),\r\n                \"ReleaseRegistry: same api version\"\r\n            );\r\n        }\r\n\r\n        // Update latest release.\r\n        factories[releaseId] = _factory;\r\n\r\n        // Set the api to the target.\r\n        releaseTargets[apiVersion] = releaseId;\r\n\r\n        // Increase our number of releases.\r\n        numReleases = releaseId + 1;\r\n\r\n        // Log the release for external listeners\r\n        emit NewRelease(releaseId, _factory, apiVersion);\r\n    }\r\n}\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP.\r\n */\r\ninterface IERC20 {\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `to`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address to, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `from` to `to` using the\r\n     * allowance mechanism. `amount` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\r\n}\r\n\r\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\r\n\r\n/**\r\n * @dev Interface for the optional metadata functions from the ERC20 standard.\r\n *\r\n * _Available since v4.1._\r\n */\r\ninterface IERC20Metadata is IERC20 {\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token.\r\n     */\r\n    function symbol() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the decimals places of the token.\r\n     */\r\n    function decimals() external view returns (uint8);\r\n}\r\n\r\n/**\r\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\r\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\r\n *\r\n * _Available since v4.7._\r\n */\r\ninterface IERC4626 is IERC20, IERC20Metadata {\r\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\r\n\r\n    event Withdraw(\r\n        address indexed sender,\r\n        address indexed receiver,\r\n        address indexed owner,\r\n        uint256 assets,\r\n        uint256 shares\r\n    );\r\n\r\n    /**\r\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\r\n     *\r\n     * - MUST be an ERC-20 token contract.\r\n     * - MUST NOT revert.\r\n     */\r\n    function asset() external view returns (address assetTokenAddress);\r\n\r\n    /**\r\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\r\n     *\r\n     * - SHOULD include any compounding that occurs from yield.\r\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\r\n     * - MUST NOT revert.\r\n     */\r\n    function totalAssets() external view returns (uint256 totalManagedAssets);\r\n\r\n    /**\r\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\r\n     * scenario where all the conditions are met.\r\n     *\r\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\r\n     * - MUST NOT show any variations depending on the caller.\r\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\r\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\r\n     * from.\r\n     */\r\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\r\n     * scenario where all the conditions are met.\r\n     *\r\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\r\n     * - MUST NOT show any variations depending on the caller.\r\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\r\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\r\n     * from.\r\n     */\r\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\r\n     * through a deposit call.\r\n     *\r\n     * - MUST return a limited value if receiver is subject to some deposit limit.\r\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\r\n     * current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\r\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\r\n     *   in the same transaction.\r\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\r\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\r\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\r\n     */\r\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\r\n     *\r\n     * - MUST emit the Deposit event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\r\n     *   deposit execution, and are accounted for during deposit.\r\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\r\n     *   approving enough underlying tokens to the Vault contract, etc).\r\n     *\r\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\r\n     */\r\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\r\n     * - MUST return a limited value if receiver is subject to some mint limit.\r\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxMint(address receiver) external view returns (uint256 maxShares);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\r\n     * current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\r\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\r\n     *   same transaction.\r\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\r\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\r\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\r\n     */\r\n    function previewMint(uint256 shares) external view returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\r\n     *\r\n     * - MUST emit the Deposit event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\r\n     *   execution, and are accounted for during mint.\r\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\r\n     *   approving enough underlying tokens to the Vault contract, etc).\r\n     *\r\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\r\n     */\r\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\r\n     * Vault, through a withdraw call.\r\n     *\r\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\r\n     * given current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\r\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\r\n     *   called\r\n     *   in the same transaction.\r\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\r\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\r\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\r\n     */\r\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\r\n     *\r\n     * - MUST emit the Withdraw event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\r\n     *   withdraw execution, and are accounted for during withdraw.\r\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\r\n     *   not having enough shares, etc).\r\n     *\r\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\r\n     * Those methods should be performed separately.\r\n     */\r\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\r\n     * through a redeem call.\r\n     *\r\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\r\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\r\n     * given current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\r\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\r\n     *   same transaction.\r\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\r\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\r\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\r\n     */\r\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\r\n     *\r\n     * - MUST emit the Withdraw event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\r\n     *   redeem execution, and are accounted for during redeem.\r\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\r\n     *   not having enough shares, etc).\r\n     *\r\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\r\n     * Those methods should be performed separately.\r\n     */\r\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\r\n}\r\n\r\ninterface IVault is IERC4626 {\r\n    // STRATEGY EVENTS\r\n    event StrategyChanged(address indexed strategy, uint256 change_type);\r\n    event StrategyReported(\r\n        address indexed strategy,\r\n        uint256 gain,\r\n        uint256 loss,\r\n        uint256 current_debt,\r\n        uint256 protocol_fees,\r\n        uint256 total_fees,\r\n        uint256 total_refunds\r\n    );\r\n    // DEBT MANAGEMENT EVENTS\r\n    event DebtUpdated(\r\n        address indexed strategy,\r\n        uint256 current_debt,\r\n        uint256 new_debt\r\n    );\r\n    // ROLE UPDATES\r\n    event RoleSet(address indexed account, uint256 role);\r\n    event UpdateRoleManager(address indexed role_manager);\r\n\r\n    event UpdateAccountant(address indexed accountant);\r\n    event UpdateDefaultQueue(address[] new_default_queue);\r\n    event UpdateUseDefaultQueue(bool use_default_queue);\r\n    event UpdatedMaxDebtForStrategy(\r\n        address indexed sender,\r\n        address indexed strategy,\r\n        uint256 new_debt\r\n    );\r\n    event UpdateDepositLimit(uint256 deposit_limit);\r\n    event UpdateMinimumTotalIdle(uint256 minimum_total_idle);\r\n    event UpdateProfitMaxUnlockTime(uint256 profit_max_unlock_time);\r\n    event DebtPurchased(address indexed strategy, uint256 amount);\r\n    event Shutdown();\r\n\r\n    struct StrategyParams {\r\n        uint256 activation;\r\n        uint256 last_report;\r\n        uint256 current_debt;\r\n        uint256 max_debt;\r\n    }\r\n\r\n    function FACTORY() external view returns (uint256);\r\n\r\n    function strategies(address) external view returns (StrategyParams memory);\r\n\r\n    function default_queue(uint256) external view returns (address);\r\n\r\n    function use_default_queue() external view returns (bool);\r\n\r\n    function minimum_total_idle() external view returns (uint256);\r\n\r\n    function deposit_limit() external view returns (uint256);\r\n\r\n    function deposit_limit_module() external view returns (address);\r\n\r\n    function withdraw_limit_module() external view returns (address);\r\n\r\n    function accountant() external view returns (address);\r\n\r\n    function roles(address) external view returns (uint256);\r\n\r\n    function role_manager() external view returns (address);\r\n\r\n    function future_role_manager() external view returns (address);\r\n\r\n    function isShutdown() external view returns (bool);\r\n\r\n    function nonces(address) external view returns (uint256);\r\n\r\n    function initialize(\r\n        address,\r\n        string memory,\r\n        string memory,\r\n        address,\r\n        uint256\r\n    ) external;\r\n\r\n    function set_accountant(address new_accountant) external;\r\n\r\n    function set_default_queue(address[] memory new_default_queue) external;\r\n\r\n    function set_use_default_queue(bool) external;\r\n\r\n    function set_deposit_limit(uint256 deposit_limit) external;\r\n\r\n    function set_deposit_limit(\r\n        uint256 deposit_limit,\r\n        bool should_override\r\n    ) external;\r\n\r\n    function set_deposit_limit_module(\r\n        address new_deposit_limit_module\r\n    ) external;\r\n\r\n    function set_deposit_limit_module(\r\n        address new_deposit_limit_module,\r\n        bool should_override\r\n    ) external;\r\n\r\n    function set_withdraw_limit_module(\r\n        address new_withdraw_limit_module\r\n    ) external;\r\n\r\n    function set_minimum_total_idle(uint256 minimum_total_idle) external;\r\n\r\n    function setProfitMaxUnlockTime(\r\n        uint256 new_profit_max_unlock_time\r\n    ) external;\r\n\r\n    function set_role(address account, uint256 role) external;\r\n\r\n    function add_role(address account, uint256 role) external;\r\n\r\n    function remove_role(address account, uint256 role) external;\r\n\r\n    function transfer_role_manager(address role_manager) external;\r\n\r\n    function accept_role_manager() external;\r\n\r\n    function unlockedShares() external view returns (uint256);\r\n\r\n    function pricePerShare() external view returns (uint256);\r\n\r\n    function get_default_queue() external view returns (address[] memory);\r\n\r\n    function process_report(\r\n        address strategy\r\n    ) external returns (uint256, uint256);\r\n\r\n    function buy_debt(address strategy, uint256 amount) external;\r\n\r\n    function add_strategy(address new_strategy) external;\r\n\r\n    function revoke_strategy(address strategy) external;\r\n\r\n    function force_revoke_strategy(address strategy) external;\r\n\r\n    function update_max_debt_for_strategy(\r\n        address strategy,\r\n        uint256 new_max_debt\r\n    ) external;\r\n\r\n    function update_debt(\r\n        address strategy,\r\n        uint256 target_debt\r\n    ) external returns (uint256);\r\n\r\n    function update_debt(\r\n        address strategy,\r\n        uint256 target_debt,\r\n        uint256 max_loss\r\n    ) external returns (uint256);\r\n\r\n    function shutdown_vault() external;\r\n\r\n    function totalIdle() external view returns (uint256);\r\n\r\n    function totalDebt() external view returns (uint256);\r\n\r\n    function apiVersion() external view returns (string memory);\r\n\r\n    function assess_share_of_unrealised_losses(\r\n        address strategy,\r\n        uint256 assets_needed\r\n    ) external view returns (uint256);\r\n\r\n    function profitMaxUnlockTime() external view returns (uint256);\r\n\r\n    function fullProfitUnlockDate() external view returns (uint256);\r\n\r\n    function profitUnlockingRate() external view returns (uint256);\r\n\r\n    function lastProfitUpdate() external view returns (uint256);\r\n\r\n    //// NON-STANDARD ERC-4626 FUNCTIONS \\\\\\\\\r\n\r\n    function withdraw(\r\n        uint256 assets,\r\n        address receiver,\r\n        address owner,\r\n        uint256 max_loss\r\n    ) external returns (uint256);\r\n\r\n    function withdraw(\r\n        uint256 assets,\r\n        address receiver,\r\n        address owner,\r\n        uint256 max_loss,\r\n        address[] memory strategies\r\n    ) external returns (uint256);\r\n\r\n    function redeem(\r\n        uint256 shares,\r\n        address receiver,\r\n        address owner,\r\n        uint256 max_loss\r\n    ) external returns (uint256);\r\n\r\n    function redeem(\r\n        uint256 shares,\r\n        address receiver,\r\n        address owner,\r\n        uint256 max_loss,\r\n        address[] memory strategies\r\n    ) external returns (uint256);\r\n\r\n    function maxWithdraw(\r\n        address owner,\r\n        uint256 max_loss\r\n    ) external view returns (uint256);\r\n\r\n    function maxWithdraw(\r\n        address owner,\r\n        uint256 max_loss,\r\n        address[] memory strategies\r\n    ) external view returns (uint256);\r\n\r\n    function maxRedeem(\r\n        address owner,\r\n        uint256 max_loss\r\n    ) external view returns (uint256);\r\n\r\n    function maxRedeem(\r\n        address owner,\r\n        uint256 max_loss,\r\n        address[] memory strategies\r\n    ) external view returns (uint256);\r\n\r\n    //// NON-STANDARD ERC-20 FUNCTIONS \\\\\\\\\r\n\r\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\r\n\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 amount,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) external returns (bool);\r\n}\r\n\r\ninterface IVaultFactory {\r\n    function deploy_new_vault(\r\n        address asset,\r\n        string memory name,\r\n        string memory symbol,\r\n        address role_manager,\r\n        uint256 profit_max_unlock_time\r\n    ) external returns (address);\r\n\r\n    function apiVersion() external view returns (string memory);\r\n}\r\n\r\n/**\r\n * @title YearnV3 Registry\r\n * @author yearn.finance\r\n * @notice\r\n *  Serves as an on chain registry to track any Yearn\r\n *  vaults and strategies that a certain party wants to\r\n *  endorse.\r\n *\r\n *  Can also be used to deploy new vaults of any specific\r\n *  API version.\r\n */\r\ncontract Registry is Governance {\r\n    /// @notice Emitted when a new vault is deployed or added.\r\n    event NewEndorsedVault(\r\n        address indexed vault,\r\n        address indexed asset,\r\n        uint256 releaseVersion,\r\n        uint256 vaultType\r\n    );\r\n\r\n    /// @notice Emitted when a vault is removed.\r\n    event RemovedVault(\r\n        address indexed vault,\r\n        address indexed asset,\r\n        uint256 releaseVersion,\r\n        uint256 vaultType\r\n    );\r\n\r\n    /// @notice Emitted when a vault is tagged which a string.\r\n    event VaultTagged(address indexed vault);\r\n\r\n    /// @notice Emitted when gov adds ore removes a `tagger`.\r\n    event UpdateTagger(address indexed account, bool status);\r\n\r\n    /// @notice Emitted when gov adds ore removes a `endorser`.\r\n    event UpdateEndorser(address indexed account, bool status);\r\n\r\n    /// @notice Can only be gov or an `endorser`.\r\n    modifier onlyEndorsers() {\r\n        _isEndorser();\r\n        _;\r\n    }\r\n\r\n    /// @notice Can only be gov or a `tagger`.\r\n    modifier onlyTaggers() {\r\n        _isTagger();\r\n        _;\r\n    }\r\n\r\n    /// @notice Check is gov or an `endorser`.\r\n    function _isEndorser() internal view {\r\n        require(msg.sender == governance || endorsers[msg.sender], \"!endorser\");\r\n    }\r\n\r\n    /// @notice Check is gov or a `tagger`.\r\n    function _isTagger() internal view {\r\n        require(msg.sender == governance || taggers[msg.sender], \"!tagger\");\r\n    }\r\n\r\n    // Struct stored for every endorsed vault or strategy for\r\n    // off chain use to easily retrieve info.\r\n    struct Info {\r\n        // The token thats being used.\r\n        address asset;\r\n        // The release number corresponding to the release registries version.\r\n        uint96 releaseVersion;\r\n        // Type of vault.\r\n        uint64 vaultType;\r\n        // Time when the vault was deployed for easier indexing.\r\n        uint128 deploymentTimestamp;\r\n        // Index the vault is at in array for easy removals.\r\n        uint64 index;\r\n        // String so that management can tag a vault with any info for FE's.\r\n        string tag;\r\n    }\r\n\r\n    // Address used to get the specific versions from.\r\n    address public immutable releaseRegistry;\r\n\r\n    // Default type used for Multi strategy \"Allocator\" vaults.\r\n    uint256 public constant MULTI_STRATEGY_TYPE = 1;\r\n\r\n    // Default type used for Single \"Tokenized\" Strategy vaults.\r\n    uint256 public constant SINGLE_STRATEGY_TYPE = 2;\r\n\r\n    // Custom name for this Registry.\r\n    string public name;\r\n\r\n    // Mapping for any address that is allowed to tag a vault.\r\n    mapping(address => bool) public taggers;\r\n\r\n    // Mapping for any address that is allowed to deploy or endorse.\r\n    mapping(address => bool) public endorsers;\r\n\r\n    // vault/strategy address => Info struct.\r\n    mapping(address => Info) public vaultInfo;\r\n\r\n    // Mapping to check if a specific `asset` has a vault.\r\n    mapping(address => bool) public assetIsUsed;\r\n\r\n    // asset => array of all endorsed vaults.\r\n    mapping(address => address[]) internal _endorsedVaults;\r\n\r\n    // Array of all tokens used as the underlying.\r\n    address[] public assets;\r\n\r\n    /**\r\n     * @param _governance Address to set as owner of the Registry.\r\n     * @param _name The custom string for this custom registry to be called.\r\n     * @param _releaseRegistry The Permissionless releaseRegistry to deploy vaults through.\r\n     */\r\n    constructor(\r\n        address _governance,\r\n        string memory _name,\r\n        address _releaseRegistry\r\n    ) Governance(_governance) {\r\n        // Set name.\r\n        name = _name;\r\n        // Set releaseRegistry.\r\n        releaseRegistry = _releaseRegistry;\r\n    }\r\n\r\n    /**\r\n     * @notice Returns the total number of assets being used as the underlying.\r\n     * @return The amount of assets.\r\n     */\r\n    function numAssets() external view virtual returns (uint256) {\r\n        return assets.length;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the full array of tokens being used.\r\n     * @return The full array of underlying tokens being used/.\r\n     */\r\n    function getAssets() external view virtual returns (address[] memory) {\r\n        return assets;\r\n    }\r\n\r\n    /**\r\n     * @notice The amount of endorsed vaults for a specific token.\r\n     * @return The amount of endorsed vaults.\r\n     */\r\n    function numEndorsedVaults(\r\n        address _asset\r\n    ) public view virtual returns (uint256) {\r\n        return _endorsedVaults[_asset].length;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the array of vaults endorsed for an `_asset`.\r\n     * @param _asset The underlying token used by the vaults.\r\n     * @return The endorsed vaults.\r\n     */\r\n    function getEndorsedVaults(\r\n        address _asset\r\n    ) external view virtual returns (address[] memory) {\r\n        return _endorsedVaults[_asset];\r\n    }\r\n\r\n    /**\r\n     * @notice Get all endorsed vaults deployed using the Registry.\r\n     * @dev This will return a nested array of all vaults deployed\r\n     * separated by their underlying asset.\r\n     *\r\n     * This is only meant for off chain viewing and should not be used during any\r\n     * on chain tx's.\r\n     *\r\n     * @return allEndorsedVaults A nested array containing all vaults.\r\n     */\r\n    function getAllEndorsedVaults()\r\n        external\r\n        view\r\n        virtual\r\n        returns (address[][] memory allEndorsedVaults)\r\n    {\r\n        address[] memory allAssets = assets;\r\n        uint256 length = assets.length;\r\n\r\n        allEndorsedVaults = new address[][](length);\r\n        for (uint256 i; i < length; ++i) {\r\n            allEndorsedVaults[i] = _endorsedVaults[allAssets[i]];\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Check if a vault is endorsed in this registry.\r\n     * @dev This will check if the `asset` variable in the struct has been\r\n     *   set for an easy external view check.\r\n     * @param _vault Address of the vault to check.\r\n     * @return . The vaults endorsement status.\r\n     */\r\n    function isEndorsed(address _vault) external view virtual returns (bool) {\r\n        return vaultInfo[_vault].asset != address(0);\r\n    }\r\n\r\n    /**\r\n     * @notice\r\n     *    Create and endorse a new multi strategy \"Allocator\"\r\n     *      vault and endorse it in this registry.\r\n     * @dev\r\n     *   Throws if caller isn't `owner`.\r\n     *   Throws if no releases are registered yet.\r\n     *   Emits a `NewEndorsedVault` event.\r\n     * @param _asset The asset that may be deposited into the new Vault.\r\n     * @param _name Specify a custom Vault name. .\r\n     * @param _symbol Specify a custom Vault symbol name.\r\n     * @param _roleManager The address authorized for guardian interactions in the new Vault.\r\n     * @param _profitMaxUnlockTime The time strategy profits will unlock over.\r\n     * @return _vault address of the newly-deployed vault\r\n     */\r\n    function newEndorsedVault(\r\n        address _asset,\r\n        string memory _name,\r\n        string memory _symbol,\r\n        address _roleManager,\r\n        uint256 _profitMaxUnlockTime\r\n    ) public virtual returns (address _vault) {\r\n        return\r\n            newEndorsedVault(\r\n                _asset,\r\n                _name,\r\n                _symbol,\r\n                _roleManager,\r\n                _profitMaxUnlockTime,\r\n                0 // Default to latest version.\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice\r\n     *    Create and endorse a new multi strategy \"Allocator\"\r\n     *      vault and endorse it in this registry.\r\n     * @dev\r\n     *   Throws if caller isn't `owner`.\r\n     *   Throws if no releases are registered yet.\r\n     *   Emits a `NewEndorsedVault` event.\r\n     * @param _asset The asset that may be deposited into the new Vault.\r\n     * @param _name Specify a custom Vault name. .\r\n     * @param _symbol Specify a custom Vault symbol name.\r\n     * @param _roleManager The address authorized for guardian interactions in the new Vault.\r\n     * @param _profitMaxUnlockTime The time strategy profits will unlock over.\r\n     * @param _releaseDelta The number of releases prior to the latest to use as a target. NOTE: Set to 0 for latest.\r\n     * @return _vault address of the newly-deployed vault\r\n     */\r\n    function newEndorsedVault(\r\n        address _asset,\r\n        string memory _name,\r\n        string memory _symbol,\r\n        address _roleManager,\r\n        uint256 _profitMaxUnlockTime,\r\n        uint256 _releaseDelta\r\n    ) public virtual onlyEndorsers returns (address _vault) {\r\n        // Get the target release based on the delta given.\r\n        uint256 _releaseTarget = ReleaseRegistry(releaseRegistry)\r\n            .numReleases() -\r\n            1 -\r\n            _releaseDelta;\r\n\r\n        // Get the factory address for that specific Api version.\r\n        address factory = ReleaseRegistry(releaseRegistry).factories(\r\n            _releaseTarget\r\n        );\r\n\r\n        // Make sure we got an actual factory\r\n        require(factory != address(0), \"Registry: unknown release\");\r\n\r\n        // Deploy New vault.\r\n        _vault = IVaultFactory(factory).deploy_new_vault(\r\n            _asset,\r\n            _name,\r\n            _symbol,\r\n            _roleManager,\r\n            _profitMaxUnlockTime\r\n        );\r\n\r\n        // Register the vault with this Registry\r\n        _registerVault(\r\n            _vault,\r\n            _asset,\r\n            _releaseTarget,\r\n            MULTI_STRATEGY_TYPE,\r\n            block.timestamp\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Endorse an already deployed multi strategy vault.\r\n     * @dev To be used with default values for `_releaseDelta`, `_vaultType`\r\n     * and `_deploymentTimestamp`.\r\n\r\n     * @param _vault Address of the vault to endorse.\r\n     */\r\n    function endorseMultiStrategyVault(address _vault) external virtual {\r\n        endorseVault(_vault, 0, MULTI_STRATEGY_TYPE, 0);\r\n    }\r\n\r\n    /**\r\n     * @notice Endorse an already deployed Single Strategy vault.\r\n     * @dev To be used with default values for `_releaseDelta`, `_vaultType`\r\n     * and `_deploymentTimestamp`.\r\n     *\r\n     * @param _vault Address of the vault to endorse.\r\n     */\r\n    function endorseSingleStrategyVault(address _vault) external virtual {\r\n        endorseVault(_vault, 0, SINGLE_STRATEGY_TYPE, 0);\r\n    }\r\n\r\n    /**\r\n     * @notice\r\n     *    Adds an existing vault to the list of \"endorsed\" vaults for that asset.\r\n     * @dev\r\n     *    Throws if caller isn't `owner`.\r\n     *    Throws if no releases are registered yet.\r\n     *    Throws if `vault`'s api version does not match the release specified.\r\n     *    Emits a `NewEndorsedVault` event.\r\n     * @param _vault The vault that will be endorsed by the Registry.\r\n     * @param _releaseDelta Specify the number of releases prior to the latest to use as a target.\r\n     * @param _vaultType Type of vault to endorse.\r\n     * @param _deploymentTimestamp The timestamp of when the vault was deployed for FE use.\r\n     */\r\n    function endorseVault(\r\n        address _vault,\r\n        uint256 _releaseDelta,\r\n        uint256 _vaultType,\r\n        uint256 _deploymentTimestamp\r\n    ) public virtual onlyEndorsers {\r\n        // Cannot endorse twice.\r\n        require(vaultInfo[_vault].asset == address(0), \"endorsed\");\r\n        require(_vaultType != 0, \"no 0 type\");\r\n        require(_vaultType <= type(uint128).max, \"type too high\");\r\n        require(_deploymentTimestamp <= block.timestamp, \"!deployment time\");\r\n\r\n        // Will underflow if no releases created yet, or targeting prior to release history\r\n        uint256 _releaseTarget = ReleaseRegistry(releaseRegistry)\r\n            .numReleases() -\r\n            1 -\r\n            _releaseDelta; // dev: no releases\r\n\r\n        // Get the API version for the target specified\r\n        string memory apiVersion = IVaultFactory(\r\n            ReleaseRegistry(releaseRegistry).factories(_releaseTarget)\r\n        ).apiVersion();\r\n\r\n        require(\r\n            keccak256(bytes(IVault(_vault).apiVersion())) ==\r\n                keccak256(bytes((apiVersion))),\r\n            \"Wrong API Version\"\r\n        );\r\n\r\n        // Add to the end of the list of vaults for asset\r\n        _registerVault(\r\n            _vault,\r\n            IVault(_vault).asset(),\r\n            _releaseTarget,\r\n            _vaultType,\r\n            _deploymentTimestamp\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @dev Function used to register a newly deployed or added vault.\r\n     *\r\n     * This well set all of the values for the vault in the `vaultInfo`\r\n     * mapping as well as add the vault and the underlying asset to any\r\n     * relevant arrays for tracking.\r\n     *\r\n     */\r\n    function _registerVault(\r\n        address _vault,\r\n        address _asset,\r\n        uint256 _releaseTarget,\r\n        uint256 _vaultType,\r\n        uint256 _deploymentTimestamp\r\n    ) internal virtual {\r\n        // Set the Info struct for this vault\r\n        vaultInfo[_vault] = Info({\r\n            asset: _asset,\r\n            releaseVersion: uint96(_releaseTarget),\r\n            vaultType: uint64(_vaultType),\r\n            deploymentTimestamp: uint128(_deploymentTimestamp),\r\n            index: uint64(_endorsedVaults[_asset].length),\r\n            tag: \"\"\r\n        });\r\n\r\n        // Add to the endorsed vaults array.\r\n        _endorsedVaults[_asset].push(_vault);\r\n\r\n        if (!assetIsUsed[_asset]) {\r\n            // We have a new asset to add\r\n            assets.push(_asset);\r\n            assetIsUsed[_asset] = true;\r\n        }\r\n\r\n        emit NewEndorsedVault(_vault, _asset, _releaseTarget, _vaultType);\r\n    }\r\n\r\n    /**\r\n     * @notice Tag a vault with a specific string.\r\n     * @dev This is available to governance to tag any vault or strategy\r\n     * on chain if desired to arbitrarily classify any vaults.\r\n     *   i.e. Certain ratings (\"A\") / Vault status (\"Shutdown\") etc.\r\n     *\r\n     * @param _vault Address of the vault or strategy to tag.\r\n     * @param _tag The string to tag the vault or strategy with.\r\n     */\r\n    function tagVault(\r\n        address _vault,\r\n        string memory _tag\r\n    ) external virtual onlyTaggers {\r\n        require(vaultInfo[_vault].asset != address(0), \"!Endorsed\");\r\n        vaultInfo[_vault].tag = _tag;\r\n\r\n        emit VaultTagged(_vault);\r\n    }\r\n\r\n    /**\r\n     * @notice Remove a `_vault`.\r\n     * @dev Can be used as an efficient way to remove a vault\r\n     * to not have to iterate over the full array.\r\n     *\r\n     * NOTE: This will not remove the asset from the `assets` array\r\n     * if it is no longer in use and will have to be done manually.\r\n     *\r\n     * @param _vault Address of the vault to remove.\r\n     */\r\n    function removeVault(address _vault) external virtual onlyEndorsers {\r\n        // Get the struct with all the vaults data.\r\n        Info memory info = vaultInfo[_vault];\r\n        require(info.asset != address(0), \"!endorsed\");\r\n        require(\r\n            _endorsedVaults[info.asset][info.index] == _vault,\r\n            \"wrong vault\"\r\n        );\r\n\r\n        // Get the vault at the end of the array\r\n        address lastVault = _endorsedVaults[info.asset][\r\n            _endorsedVaults[info.asset].length - 1\r\n        ];\r\n\r\n        // If `_vault` is not the last item in the array.\r\n        if (lastVault != _vault) {\r\n            // Set the last index to the spot we are removing.\r\n            _endorsedVaults[info.asset][info.index] = lastVault;\r\n\r\n            // Update the index of the vault we moved\r\n            vaultInfo[lastVault].index = uint64(info.index);\r\n        }\r\n\r\n        // Pop the last item off the array.\r\n        _endorsedVaults[info.asset].pop();\r\n\r\n        // Emit the event.\r\n        emit RemovedVault(\r\n            _vault,\r\n            info.asset,\r\n            info.releaseVersion,\r\n            info.vaultType\r\n        );\r\n\r\n        // Delete the struct.\r\n        delete vaultInfo[_vault];\r\n    }\r\n\r\n    /**\r\n     * @notice Removes a specific `_asset` at `_index` from `assets`.\r\n     * @dev Can be used if an asset is no longer in use after a vault or\r\n     * strategy has also been removed.\r\n     *\r\n     * @param _asset The asset to remove from the array.\r\n     * @param _index The index it sits at.\r\n     */\r\n    function removeAsset(\r\n        address _asset,\r\n        uint256 _index\r\n    ) external virtual onlyEndorsers {\r\n        require(assetIsUsed[_asset], \"!in use\");\r\n        require(_endorsedVaults[_asset].length == 0, \"still in use\");\r\n        require(assets[_index] == _asset, \"wrong asset\");\r\n\r\n        // Replace `_asset` with the last index.\r\n        assets[_index] = assets[assets.length - 1];\r\n\r\n        // Pop last item off the array.\r\n        assets.pop();\r\n\r\n        // No longer used.\r\n        assetIsUsed[_asset] = false;\r\n    }\r\n\r\n    /**\r\n     * @notice Set a new address to be able to endorse or remove an existing endorser.\r\n     * @param _account The address to set.\r\n     * @param _canEndorse Bool if the `_account` can or cannot endorse.\r\n     */\r\n    function setEndorser(\r\n        address _account,\r\n        bool _canEndorse\r\n    ) external virtual onlyGovernance {\r\n        endorsers[_account] = _canEndorse;\r\n\r\n        emit UpdateEndorser(_account, _canEndorse);\r\n    }\r\n\r\n    /**\r\n     * @notice Set a new address to be able to tag a vault.\r\n     * @param _account The address to set.\r\n     * @param _canTag Bool if the `_account` can or cannot tag.\r\n     */\r\n    function setTagger(\r\n        address _account,\r\n        bool _canTag\r\n    ) external virtual onlyGovernance {\r\n        taggers[_account] = _canTag;\r\n\r\n        emit UpdateTagger(_account, _canTag);\r\n    }\r\n}\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\r\n\r\n/**\r\n * @dev Standard math utilities missing in the Solidity language.\r\n */\r\nlibrary Math {\r\n    enum Rounding {\r\n        Down, // Toward negative infinity\r\n        Up, // Toward infinity\r\n        Zero // Toward zero\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the largest of two numbers.\r\n     */\r\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a > b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the smallest of two numbers.\r\n     */\r\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a < b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the average of two numbers. The result is rounded towards\r\n     * zero.\r\n     */\r\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b) / 2 can overflow.\r\n        return (a & b) + (a ^ b) / 2;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the ceiling of the division of two numbers.\r\n     *\r\n     * This differs from standard division with `/` in that it rounds up instead\r\n     * of rounding down.\r\n     */\r\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b - 1) / b can overflow on addition, so we distribute.\r\n        return a == 0 ? 0 : (a - 1) / b + 1;\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\r\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\r\n     * with further edits by Uniswap Labs also under MIT license.\r\n     */\r\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\r\n        unchecked {\r\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\r\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\r\n            // variables such that product = prod1 * 2^256 + prod0.\r\n            uint256 prod0; // Least significant 256 bits of the product\r\n            uint256 prod1; // Most significant 256 bits of the product\r\n            assembly {\r\n                let mm := mulmod(x, y, not(0))\r\n                prod0 := mul(x, y)\r\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\r\n            }\r\n\r\n            // Handle non-overflow cases, 256 by 256 division.\r\n            if (prod1 == 0) {\r\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\r\n                // The surrounding unchecked block does not change this fact.\r\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\r\n                return prod0 / denominator;\r\n            }\r\n\r\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\r\n            require(denominator > prod1, \"Math: mulDiv overflow\");\r\n\r\n            ///////////////////////////////////////////////\r\n            // 512 by 256 division.\r\n            ///////////////////////////////////////////////\r\n\r\n            // Make division exact by subtracting the remainder from [prod1 prod0].\r\n            uint256 remainder;\r\n            assembly {\r\n                // Compute remainder using mulmod.\r\n                remainder := mulmod(x, y, denominator)\r\n\r\n                // Subtract 256 bit number from 512 bit number.\r\n                prod1 := sub(prod1, gt(remainder, prod0))\r\n                prod0 := sub(prod0, remainder)\r\n            }\r\n\r\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\r\n            // See https://cs.stackexchange.com/q/138556/92363.\r\n\r\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\r\n            uint256 twos = denominator & (~denominator + 1);\r\n            assembly {\r\n                // Divide denominator by twos.\r\n                denominator := div(denominator, twos)\r\n\r\n                // Divide [prod1 prod0] by twos.\r\n                prod0 := div(prod0, twos)\r\n\r\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\r\n                twos := add(div(sub(0, twos), twos), 1)\r\n            }\r\n\r\n            // Shift in bits from prod1 into prod0.\r\n            prod0 |= prod1 * twos;\r\n\r\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\r\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\r\n            // four bits. That is, denominator * inv = 1 mod 2^4.\r\n            uint256 inverse = (3 * denominator) ^ 2;\r\n\r\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\r\n            // in modular arithmetic, doubling the correct bits in each step.\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\r\n\r\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\r\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\r\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\r\n            // is no longer required.\r\n            result = prod0 * inverse;\r\n            return result;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\r\n     */\r\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\r\n        uint256 result = mulDiv(x, y, denominator);\r\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\r\n            result += 1;\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\r\n     *\r\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\r\n     */\r\n    function sqrt(uint256 a) internal pure returns (uint256) {\r\n        if (a == 0) {\r\n            return 0;\r\n        }\r\n\r\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\r\n        //\r\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\r\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\r\n        //\r\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\r\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\r\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\r\n        //\r\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\r\n        uint256 result = 1 << (log2(a) >> 1);\r\n\r\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\r\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\r\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\r\n        // into the expected uint128 result.\r\n        unchecked {\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            return min(result, a / result);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates sqrt(a), following the selected rounding direction.\r\n     */\r\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = sqrt(a);\r\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 128;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 64;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 32;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 16;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                value >>= 8;\r\n                result += 8;\r\n            }\r\n            if (value >> 4 > 0) {\r\n                value >>= 4;\r\n                result += 4;\r\n            }\r\n            if (value >> 2 > 0) {\r\n                value >>= 2;\r\n                result += 2;\r\n            }\r\n            if (value >> 1 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log2(value);\r\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >= 10 ** 64) {\r\n                value /= 10 ** 64;\r\n                result += 64;\r\n            }\r\n            if (value >= 10 ** 32) {\r\n                value /= 10 ** 32;\r\n                result += 32;\r\n            }\r\n            if (value >= 10 ** 16) {\r\n                value /= 10 ** 16;\r\n                result += 16;\r\n            }\r\n            if (value >= 10 ** 8) {\r\n                value /= 10 ** 8;\r\n                result += 8;\r\n            }\r\n            if (value >= 10 ** 4) {\r\n                value /= 10 ** 4;\r\n                result += 4;\r\n            }\r\n            if (value >= 10 ** 2) {\r\n                value /= 10 ** 2;\r\n                result += 2;\r\n            }\r\n            if (value >= 10 ** 1) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log10(value);\r\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 256, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     *\r\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\r\n     */\r\n    function log256(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 16;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 8;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 4;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 2;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log256(value);\r\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\r\n        }\r\n    }\r\n}\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\r\n\r\n/**\r\n * @dev Provides information about the current execution context, including the\r\n * sender of the transaction and its data. While these are generally available\r\n * via msg.sender and msg.data, they should not be accessed in such a direct\r\n * manner, since when dealing with meta-transactions the account sending and\r\n * paying for execution may not be the actual sender (as far as an application\r\n * is concerned).\r\n *\r\n * This contract is only required for intermediate, library-like contracts.\r\n */\r\nabstract contract Context {\r\n    function _msgSender() internal view virtual returns (address) {\r\n        return msg.sender;\r\n    }\r\n\r\n    function _msgData() internal view virtual returns (bytes calldata) {\r\n        return msg.data;\r\n    }\r\n\r\n    function _contextSuffixLength() internal view virtual returns (uint256) {\r\n        return 0;\r\n    }\r\n}\r\n\r\n/**\r\n * @dev Implementation of the {IERC20} interface.\r\n *\r\n * This implementation is agnostic to the way tokens are created. This means\r\n * that a supply mechanism has to be added in a derived contract using {_mint}.\r\n * For a generic mechanism see {ERC20PresetMinterPauser}.\r\n *\r\n * TIP: For a detailed writeup see our guide\r\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\r\n * to implement supply mechanisms].\r\n *\r\n * The default value of {decimals} is 18. To change this, you should override\r\n * this function so it returns a different value.\r\n *\r\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\r\n * instead returning `false` on failure. This behavior is nonetheless\r\n * conventional and does not conflict with the expectations of ERC20\r\n * applications.\r\n *\r\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\r\n * This allows applications to reconstruct the allowance for all accounts just\r\n * by listening to said events. Other implementations of the EIP may not emit\r\n * these events, as it isn't required by the specification.\r\n *\r\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\r\n * functions have been added to mitigate the well-known issues around setting\r\n * allowances. See {IERC20-approve}.\r\n */\r\ncontract ERC20 is Context, IERC20, IERC20Metadata {\r\n    mapping(address => uint256) private _balances;\r\n\r\n    mapping(address => mapping(address => uint256)) private _allowances;\r\n\r\n    uint256 private _totalSupply;\r\n\r\n    string private _name;\r\n    string private _symbol;\r\n\r\n    /**\r\n     * @dev Sets the values for {name} and {symbol}.\r\n     *\r\n     * All two of these values are immutable: they can only be set once during\r\n     * construction.\r\n     */\r\n    constructor(string memory name_, string memory symbol_) {\r\n        _name = name_;\r\n        _symbol = symbol_;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() public view virtual override returns (string memory) {\r\n        return _name;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token, usually a shorter version of the\r\n     * name.\r\n     */\r\n    function symbol() public view virtual override returns (string memory) {\r\n        return _symbol;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the number of decimals used to get its user representation.\r\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\r\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\r\n     *\r\n     * Tokens usually opt for a value of 18, imitating the relationship between\r\n     * Ether and Wei. This is the default value returned by this function, unless\r\n     * it's overridden.\r\n     *\r\n     * NOTE: This information is only used for _display_ purposes: it in\r\n     * no way affects any of the arithmetic of the contract, including\r\n     * {IERC20-balanceOf} and {IERC20-transfer}.\r\n     */\r\n    function decimals() public view virtual override returns (uint8) {\r\n        return 18;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-totalSupply}.\r\n     */\r\n    function totalSupply() public view virtual override returns (uint256) {\r\n        return _totalSupply;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-balanceOf}.\r\n     */\r\n    function balanceOf(address account) public view virtual override returns (uint256) {\r\n        return _balances[account];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transfer}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `to` cannot be the zero address.\r\n     * - the caller must have a balance of at least `amount`.\r\n     */\r\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\r\n        address owner = _msgSender();\r\n        _transfer(owner, to, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-allowance}.\r\n     */\r\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\r\n        return _allowances[owner][spender];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-approve}.\r\n     *\r\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\r\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\r\n        address owner = _msgSender();\r\n        _approve(owner, spender, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transferFrom}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance. This is not\r\n     * required by the EIP. See the note at the beginning of {ERC20}.\r\n     *\r\n     * NOTE: Does not update the allowance if the current allowance\r\n     * is the maximum `uint256`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `from` and `to` cannot be the zero address.\r\n     * - `from` must have a balance of at least `amount`.\r\n     * - the caller must have allowance for ``from``'s tokens of at least\r\n     * `amount`.\r\n     */\r\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\r\n        address spender = _msgSender();\r\n        _spendAllowance(from, spender, amount);\r\n        _transfer(from, to, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\r\n        address owner = _msgSender();\r\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `spender` must have allowance for the caller of at least\r\n     * `subtractedValue`.\r\n     */\r\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\r\n        address owner = _msgSender();\r\n        uint256 currentAllowance = allowance(owner, spender);\r\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\r\n        unchecked {\r\n            _approve(owner, spender, currentAllowance - subtractedValue);\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Moves `amount` of tokens from `from` to `to`.\r\n     *\r\n     * This internal function is equivalent to {transfer}, and can be used to\r\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `from` cannot be the zero address.\r\n     * - `to` cannot be the zero address.\r\n     * - `from` must have a balance of at least `amount`.\r\n     */\r\n    function _transfer(address from, address to, uint256 amount) internal virtual {\r\n        require(from != address(0), \"ERC20: transfer from the zero address\");\r\n        require(to != address(0), \"ERC20: transfer to the zero address\");\r\n\r\n        _beforeTokenTransfer(from, to, amount);\r\n\r\n        uint256 fromBalance = _balances[from];\r\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\r\n        unchecked {\r\n            _balances[from] = fromBalance - amount;\r\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\r\n            // decrementing then incrementing.\r\n            _balances[to] += amount;\r\n        }\r\n\r\n        emit Transfer(from, to, amount);\r\n\r\n        _afterTokenTransfer(from, to, amount);\r\n    }\r\n\r\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\r\n     * the total supply.\r\n     *\r\n     * Emits a {Transfer} event with `from` set to the zero address.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     */\r\n    function _mint(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: mint to the zero address\");\r\n\r\n        _beforeTokenTransfer(address(0), account, amount);\r\n\r\n        _totalSupply += amount;\r\n        unchecked {\r\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\r\n            _balances[account] += amount;\r\n        }\r\n        emit Transfer(address(0), account, amount);\r\n\r\n        _afterTokenTransfer(address(0), account, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from `account`, reducing the\r\n     * total supply.\r\n     *\r\n     * Emits a {Transfer} event with `to` set to the zero address.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     * - `account` must have at least `amount` tokens.\r\n     */\r\n    function _burn(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: burn from the zero address\");\r\n\r\n        _beforeTokenTransfer(account, address(0), amount);\r\n\r\n        uint256 accountBalance = _balances[account];\r\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\r\n        unchecked {\r\n            _balances[account] = accountBalance - amount;\r\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\r\n            _totalSupply -= amount;\r\n        }\r\n\r\n        emit Transfer(account, address(0), amount);\r\n\r\n        _afterTokenTransfer(account, address(0), amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\r\n     *\r\n     * This internal function is equivalent to `approve`, and can be used to\r\n     * e.g. set automatic allowances for certain subsystems, etc.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `owner` cannot be the zero address.\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\r\n        require(owner != address(0), \"ERC20: approve from the zero address\");\r\n        require(spender != address(0), \"ERC20: approve to the zero address\");\r\n\r\n        _allowances[owner][spender] = amount;\r\n        emit Approval(owner, spender, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\r\n     *\r\n     * Does not update the allowance amount in case of infinite allowance.\r\n     * Revert if not enough allowance is available.\r\n     *\r\n     * Might emit an {Approval} event.\r\n     */\r\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\r\n        uint256 currentAllowance = allowance(owner, spender);\r\n        if (currentAllowance != type(uint256).max) {\r\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\r\n            unchecked {\r\n                _approve(owner, spender, currentAllowance - amount);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Hook that is called before any transfer of tokens. This includes\r\n     * minting and burning.\r\n     *\r\n     * Calling conditions:\r\n     *\r\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * will be transferred to `to`.\r\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\r\n     * - `from` and `to` are never both zero.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\r\n\r\n    /**\r\n     * @dev Hook that is called after any transfer of tokens. This includes\r\n     * minting and burning.\r\n     *\r\n     * Calling conditions:\r\n     *\r\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * has been transferred to `to`.\r\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\r\n     * - `from` and `to` are never both zero.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\r\n}\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\r\n\r\n/**\r\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\r\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\r\n *\r\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\r\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\r\n * need to send a transaction, and thus is not required to hold Ether at all.\r\n *\r\n * ==== Security Considerations\r\n *\r\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\r\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\r\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\r\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\r\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\r\n * generally recommended is:\r\n *\r\n * ```solidity\r\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\r\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\r\n *     doThing(..., value);\r\n * }\r\n *\r\n * function doThing(..., uint256 value) public {\r\n *     token.safeTransferFrom(msg.sender, address(this), value);\r\n *     ...\r\n * }\r\n * ```\r\n *\r\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\r\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\r\n * {SafeERC20-safeTransferFrom}).\r\n *\r\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\r\n * contracts should have entry points that don't rely on permit.\r\n */\r\ninterface IERC20Permit {\r\n    /**\r\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\r\n     * given ``owner``'s signed approval.\r\n     *\r\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\r\n     * ordering also apply here.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `deadline` must be a timestamp in the future.\r\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\r\n     * over the EIP712-formatted function arguments.\r\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\r\n     *\r\n     * For more information on the signature format, see the\r\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\r\n     * section].\r\n     *\r\n     * CAUTION: See Security Considerations above.\r\n     */\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) external;\r\n\r\n    /**\r\n     * @dev Returns the current nonce for `owner`. This value must be\r\n     * included whenever a signature is generated for {permit}.\r\n     *\r\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\r\n     * prevents a signature from being used multiple times.\r\n     */\r\n    function nonces(address owner) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\r\n     */\r\n    // solhint-disable-next-line func-name-mixedcase\r\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\r\n}\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\r\n\r\n/**\r\n * @dev Collection of functions related to the address type\r\n */\r\nlibrary Address {\r\n    /**\r\n     * @dev Returns true if `account` is a contract.\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * It is unsafe to assume that an address for which this function returns\r\n     * false is an externally-owned account (EOA) and not a contract.\r\n     *\r\n     * Among others, `isContract` will return false for the following\r\n     * types of addresses:\r\n     *\r\n     *  - an externally-owned account\r\n     *  - a contract in construction\r\n     *  - an address where a contract will be created\r\n     *  - an address where a contract lived, but was destroyed\r\n     *\r\n     * Furthermore, `isContract` will also return true if the target contract within\r\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\r\n     * which only has an effect at the end of a transaction.\r\n     * ====\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\r\n     *\r\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\r\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\r\n     * constructor.\r\n     * ====\r\n     */\r\n    function isContract(address account) internal view returns (bool) {\r\n        // This method relies on extcodesize/address.code.length, which returns 0\r\n        // for contracts in construction, since the code is only stored at the end\r\n        // of the constructor execution.\r\n\r\n        return account.code.length > 0;\r\n    }\r\n\r\n    /**\r\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\r\n     * `recipient`, forwarding all available gas and reverting on errors.\r\n     *\r\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\r\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\r\n     * imposed by `transfer`, making them unable to receive funds via\r\n     * `transfer`. {sendValue} removes this limitation.\r\n     *\r\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\r\n     *\r\n     * IMPORTANT: because control is transferred to `recipient`, care must be\r\n     * taken to not create reentrancy vulnerabilities. Consider using\r\n     * {ReentrancyGuard} or the\r\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\r\n     */\r\n    function sendValue(address payable recipient, uint256 amount) internal {\r\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\r\n\r\n        (bool success, ) = recipient.call{value: amount}(\"\");\r\n        require(success, \"Address: unable to send value, recipient may have reverted\");\r\n    }\r\n\r\n    /**\r\n     * @dev Performs a Solidity function call using a low level `call`. A\r\n     * plain `call` is an unsafe replacement for a function call: use this\r\n     * function instead.\r\n     *\r\n     * If `target` reverts with a revert reason, it is bubbled up by this\r\n     * function (like regular Solidity function calls).\r\n     *\r\n     * Returns the raw returned data. To convert to the expected return value,\r\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `target` must be a contract.\r\n     * - calling `target` with `data` must not revert.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\r\n     * `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but also transferring `value` wei to `target`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the calling contract must have an ETH balance of at least `value`.\r\n     * - the called Solidity function must be `payable`.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\r\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(\r\n        address target,\r\n        bytes memory data,\r\n        uint256 value,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\r\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\r\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.staticcall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.delegatecall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\r\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\r\n     *\r\n     * _Available since v4.8._\r\n     */\r\n    function verifyCallResultFromTarget(\r\n        address target,\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        if (success) {\r\n            if (returndata.length == 0) {\r\n                // only check isContract if the call was successful and the return data is empty\r\n                // otherwise we already know that it was a contract\r\n                require(isContract(target), \"Address: call to non-contract\");\r\n            }\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\r\n     * revert reason or using the provided one.\r\n     *\r\n     * _Available since v4.3._\r\n     */\r\n    function verifyCallResult(\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal pure returns (bytes memory) {\r\n        if (success) {\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\r\n        // Look for revert reason and bubble it up if present\r\n        if (returndata.length > 0) {\r\n            // The easiest way to bubble the revert reason is using memory via assembly\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                let returndata_size := mload(returndata)\r\n                revert(add(32, returndata), returndata_size)\r\n            }\r\n        } else {\r\n            revert(errorMessage);\r\n        }\r\n    }\r\n}\r\n\r\n/**\r\n * @title SafeERC20\r\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\r\n * contract returns false). Tokens that return no value (and instead revert or\r\n * throw on failure) are also supported, non-reverting calls are assumed to be\r\n * successful.\r\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\r\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\r\n */\r\nlibrary SafeERC20 {\r\n    using Address for address;\r\n\r\n    /**\r\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\r\n    }\r\n\r\n    /**\r\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\r\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\r\n    }\r\n\r\n    /**\r\n     * @dev Deprecated. This function has issues similar to the ones found in\r\n     * {IERC20-approve}, and its usage is discouraged.\r\n     *\r\n     * Whenever possible, use {safeIncreaseAllowance} and\r\n     * {safeDecreaseAllowance} instead.\r\n     */\r\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\r\n        // safeApprove should only be called when setting an initial allowance,\r\n        // or when resetting it to zero. To increase and decrease it, use\r\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\r\n        require(\r\n            (value == 0) || (token.allowance(address(this), spender) == 0),\r\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\r\n        );\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\r\n    }\r\n\r\n    /**\r\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        uint256 oldAllowance = token.allowance(address(this), spender);\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\r\n    }\r\n\r\n    /**\r\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        unchecked {\r\n            uint256 oldAllowance = token.allowance(address(this), spender);\r\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\r\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\r\n     * to be set to zero before setting it to a non-zero value, such as USDT.\r\n     */\r\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\r\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\r\n\r\n        if (!_callOptionalReturnBool(token, approvalCall)) {\r\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\r\n            _callOptionalReturn(token, approvalCall);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\r\n     * Revert on invalid signature.\r\n     */\r\n    function safePermit(\r\n        IERC20Permit token,\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) internal {\r\n        uint256 nonceBefore = token.nonces(owner);\r\n        token.permit(owner, spender, value, deadline, v, r, s);\r\n        uint256 nonceAfter = token.nonces(owner);\r\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     */\r\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\r\n        // the target address contains contract code and also asserts for success in the low-level call.\r\n\r\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\r\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     *\r\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\r\n     */\r\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\r\n        // and not revert is the subcall reverts.\r\n\r\n        (bool success, bytes memory returndata) = address(token).call(data);\r\n        return\r\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\r\n    }\r\n}\r\n\r\n/// @title Accountant.\r\n/// @dev Will charge fees, issue refunds, and run health check on any reported\r\n///     gains or losses during a strategy's report.\r\ncontract Accountant {\r\n    using SafeERC20 for ERC20;\r\n\r\n    /// @notice An event emitted when a vault is added or removed.\r\n    event VaultChanged(address indexed vault, ChangeType change);\r\n\r\n    /// @notice An event emitted when the default fee configuration is updated.\r\n    event UpdateDefaultFeeConfig(Fee defaultFeeConfig);\r\n\r\n    /// @notice An event emitted when the future fee manager is set.\r\n    event SetFutureFeeManager(address indexed futureFeeManager);\r\n\r\n    /// @notice An event emitted when a new fee manager is accepted.\r\n    event NewFeeManager(address indexed feeManager);\r\n\r\n    /// @notice An event emitted when a new vault manager is set.\r\n    event UpdateVaultManager(address indexed newVaultManager);\r\n\r\n    /// @notice An event emitted when the fee recipient is updated.\r\n    event UpdateFeeRecipient(\r\n        address indexed oldFeeRecipient,\r\n        address indexed newFeeRecipient\r\n    );\r\n\r\n    /// @notice An event emitted when a custom fee configuration is updated.\r\n    event UpdateCustomFeeConfig(address indexed vault, Fee custom_config);\r\n\r\n    /// @notice An event emitted when a custom fee configuration is removed.\r\n    event RemovedCustomFeeConfig(address indexed vault);\r\n\r\n    /// @notice An event emitted when the `maxLoss` parameter is updated.\r\n    event UpdateMaxLoss(uint256 maxLoss);\r\n\r\n    /// @notice An event emitted when rewards are distributed.\r\n    event DistributeRewards(address indexed token, uint256 rewards);\r\n\r\n    /// @notice Enum defining change types (added or removed).\r\n    enum ChangeType {\r\n        NULL,\r\n        ADDED,\r\n        REMOVED\r\n    }\r\n\r\n    /// @notice Struct representing fee details.\r\n    struct Fee {\r\n        uint16 managementFee; // Annual management fee to charge.\r\n        uint16 performanceFee; // Performance fee to charge.\r\n        uint16 refundRatio; // Refund ratio to give back on losses.\r\n        uint16 maxFee; // Max fee allowed as a percent of gain.\r\n        uint16 maxGain; // Max percent gain a strategy can report.\r\n        uint16 maxLoss; // Max percent loss a strategy can report.\r\n        bool custom; // Flag to set for custom configs.\r\n    }\r\n\r\n    modifier onlyFeeManager() {\r\n        _checkFeeManager();\r\n        _;\r\n    }\r\n\r\n    modifier onlyVaultOrFeeManager() {\r\n        _checkVaultOrFeeManager();\r\n        _;\r\n    }\r\n\r\n    modifier onlyFeeManagerOrRecipient() {\r\n        _checkFeeManagerOrRecipient();\r\n        _;\r\n    }\r\n\r\n    modifier onlyAddedVaults() {\r\n        _checkVaultIsAdded();\r\n        _;\r\n    }\r\n\r\n    function _checkFeeManager() internal view virtual {\r\n        require(msg.sender == feeManager, \"!fee manager\");\r\n    }\r\n\r\n    function _checkVaultOrFeeManager() internal view virtual {\r\n        require(\r\n            msg.sender == feeManager || msg.sender == vaultManager,\r\n            \"!vault manager\"\r\n        );\r\n    }\r\n\r\n    function _checkFeeManagerOrRecipient() internal view virtual {\r\n        require(\r\n            msg.sender == feeRecipient || msg.sender == feeManager,\r\n            \"!recipient\"\r\n        );\r\n    }\r\n\r\n    function _checkVaultIsAdded() internal view virtual {\r\n        require(vaults[msg.sender], \"vault not added\");\r\n    }\r\n\r\n    /// @notice Constant defining the maximum basis points.\r\n    uint256 internal constant MAX_BPS = 10_000;\r\n\r\n    /// @notice Constant defining the number of seconds in a year.\r\n    uint256 internal constant SECS_PER_YEAR = 31_556_952;\r\n\r\n    /// @notice Constant defining the management fee threshold.\r\n    uint16 public constant MANAGEMENT_FEE_THRESHOLD = 200;\r\n\r\n    /// @notice Constant defining the performance fee threshold.\r\n    uint16 public constant PERFORMANCE_FEE_THRESHOLD = 5_000;\r\n\r\n    /// @notice The amount of max loss to use when redeeming from vaults.\r\n    uint256 public maxLoss;\r\n\r\n    /// @notice The address of the fee manager.\r\n    address public feeManager;\r\n\r\n    /// @notice The address of the fee recipient.\r\n    address public feeRecipient;\r\n\r\n    /// @notice An address that can add or remove vaults.\r\n    address public vaultManager;\r\n\r\n    /// @notice The address of the future fee manager.\r\n    address public futureFeeManager;\r\n\r\n    /// @notice The default fee configuration.\r\n    Fee public defaultConfig;\r\n\r\n    /// @notice Mapping to track added vaults.\r\n    mapping(address => bool) public vaults;\r\n\r\n    /// @notice Mapping vault => custom Fee config if any.\r\n    mapping(address => Fee) public customConfig;\r\n\r\n    /// @notice Mapping vault => strategy => flag for one time healthcheck skips.\r\n    mapping(address => mapping(address => bool)) skipHealthCheck;\r\n\r\n    constructor(\r\n        address _feeManager,\r\n        address _feeRecipient,\r\n        uint16 defaultManagement,\r\n        uint16 defaultPerformance,\r\n        uint16 defaultRefund,\r\n        uint16 defaultMaxFee,\r\n        uint16 defaultMaxGain,\r\n        uint16 defaultMaxLoss\r\n    ) {\r\n        require(_feeManager != address(0), \"ZERO ADDRESS\");\r\n        require(_feeRecipient != address(0), \"ZERO ADDRESS\");\r\n\r\n        feeManager = _feeManager;\r\n        feeRecipient = _feeRecipient;\r\n\r\n        _updateDefaultConfig(\r\n            defaultManagement,\r\n            defaultPerformance,\r\n            defaultRefund,\r\n            defaultMaxFee,\r\n            defaultMaxGain,\r\n            defaultMaxLoss\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Called by a vault when a `strategy` is reporting.\r\n     * @dev The msg.sender must have been added to the `vaults` mapping.\r\n     * @param strategy Address of the strategy reporting.\r\n     * @param gain Amount of the gain if any.\r\n     * @param loss Amount of the loss if any.\r\n     * @return totalFees if any to charge.\r\n     * @return totalRefunds if any for the vault to pull.\r\n     */\r\n    function report(\r\n        address strategy,\r\n        uint256 gain,\r\n        uint256 loss\r\n    )\r\n        public\r\n        virtual\r\n        onlyAddedVaults\r\n        returns (uint256 totalFees, uint256 totalRefunds)\r\n    {\r\n        // Declare the config to use as the custom.\r\n        Fee memory fee = customConfig[msg.sender];\r\n\r\n        // Check if there is a custom config to use.\r\n        if (!fee.custom) {\r\n            // Otherwise use the default.\r\n            fee = defaultConfig;\r\n        }\r\n\r\n        // Retrieve the strategy's params from the vault.\r\n        IVault.StrategyParams memory strategyParams = IVault(msg.sender)\r\n            .strategies(strategy);\r\n\r\n        // Charge management fees no matter gain or loss.\r\n        if (fee.managementFee > 0) {\r\n            // Time since the last harvest.\r\n            uint256 duration = block.timestamp - strategyParams.last_report;\r\n            // managementFee is an annual amount, so charge based on the time passed.\r\n            totalFees = ((strategyParams.current_debt *\r\n                duration *\r\n                (fee.managementFee)) /\r\n                MAX_BPS /\r\n                SECS_PER_YEAR);\r\n        }\r\n\r\n        // Only charge performance fees if there is a gain.\r\n        if (gain > 0) {\r\n            // If we are skipping the healthcheck this report\r\n            if (skipHealthCheck[msg.sender][strategy]) {\r\n                // Make sure it is reset for the next one.\r\n                skipHealthCheck[msg.sender][strategy] = false;\r\n\r\n                // Setting `maxGain` to 0 will disable the healthcheck on profits.\r\n            } else if (fee.maxGain > 0) {\r\n                require(\r\n                    gain <=\r\n                        (strategyParams.current_debt * (fee.maxGain)) / MAX_BPS,\r\n                    \"too much gain\"\r\n                );\r\n            }\r\n\r\n            totalFees += (gain * (fee.performanceFee)) / MAX_BPS;\r\n        } else {\r\n            // If we are skipping the healthcheck this report\r\n            if (skipHealthCheck[msg.sender][strategy]) {\r\n                // Make sure it is reset for the next one.\r\n                skipHealthCheck[msg.sender][strategy] = false;\r\n\r\n                // Setting `maxLoss` to 10_000 will disable the healthcheck on losses.\r\n            } else if (fee.maxLoss < MAX_BPS) {\r\n                require(\r\n                    loss <=\r\n                        (strategyParams.current_debt * (fee.maxLoss)) / MAX_BPS,\r\n                    \"too much loss\"\r\n                );\r\n            }\r\n\r\n            // Means we should have a loss.\r\n            if (fee.refundRatio > 0) {\r\n                // Cache the underlying asset the vault uses.\r\n                address asset = IVault(msg.sender).asset();\r\n                // Give back either all we have or based on the refund ratio.\r\n                totalRefunds = Math.min(\r\n                    (loss * (fee.refundRatio)) / MAX_BPS,\r\n                    ERC20(asset).balanceOf(address(this))\r\n                );\r\n\r\n                if (totalRefunds > 0) {\r\n                    // Approve the vault to pull the underlying asset.\r\n                    _checkAllowance(msg.sender, asset, totalRefunds);\r\n                }\r\n            }\r\n        }\r\n\r\n        // 0 Max fee means it is not enforced.\r\n        if (fee.maxFee > 0) {\r\n            // Ensure fee does not exceed the maxFee %.\r\n            totalFees = Math.min((gain * (fee.maxFee)) / MAX_BPS, totalFees);\r\n        }\r\n\r\n        return (totalFees, totalRefunds);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to add a new vault for this accountant to charge fees for.\r\n     * @dev This is not used to set any of the fees for the specific vault or strategy. Each fee will be set separately.\r\n     * @param vault The address of a vault to allow to use this accountant.\r\n     */\r\n    function addVault(address vault) external virtual onlyVaultOrFeeManager {\r\n        // Ensure the vault has not already been added.\r\n        require(!vaults[vault], \"already added\");\r\n\r\n        vaults[vault] = true;\r\n\r\n        emit VaultChanged(vault, ChangeType.ADDED);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to remove a vault from this accountant's fee charging list.\r\n     * @param vault The address of the vault to be removed from this accountant.\r\n     */\r\n    function removeVault(address vault) external virtual onlyVaultOrFeeManager {\r\n        // Ensure the vault has been previously added.\r\n        require(vaults[vault], \"not added\");\r\n\r\n        address asset = IVault(vault).asset();\r\n        // Remove any allowances left.\r\n        if (ERC20(asset).allowance(address(this), vault) != 0) {\r\n            ERC20(asset).safeApprove(vault, 0);\r\n        }\r\n\r\n        vaults[vault] = false;\r\n\r\n        emit VaultChanged(vault, ChangeType.REMOVED);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to update the default fee configuration used for \r\n        all strategies that don't have a custom config set.\r\n     * @param defaultManagement Default annual management fee to charge.\r\n     * @param defaultPerformance Default performance fee to charge.\r\n     * @param defaultRefund Default refund ratio to give back on losses.\r\n     * @param defaultMaxFee Default max fee to allow as a percent of gain.\r\n     * @param defaultMaxGain Default max percent gain a strategy can report.\r\n     * @param defaultMaxLoss Default max percent loss a strategy can report.\r\n     */\r\n    function updateDefaultConfig(\r\n        uint16 defaultManagement,\r\n        uint16 defaultPerformance,\r\n        uint16 defaultRefund,\r\n        uint16 defaultMaxFee,\r\n        uint16 defaultMaxGain,\r\n        uint16 defaultMaxLoss\r\n    ) external virtual onlyFeeManager {\r\n        _updateDefaultConfig(\r\n            defaultManagement,\r\n            defaultPerformance,\r\n            defaultRefund,\r\n            defaultMaxFee,\r\n            defaultMaxGain,\r\n            defaultMaxLoss\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @dev Updates the Accountant's default fee config.\r\n     *   Is used during deployment and during any future updates.\r\n     */\r\n    function _updateDefaultConfig(\r\n        uint16 defaultManagement,\r\n        uint16 defaultPerformance,\r\n        uint16 defaultRefund,\r\n        uint16 defaultMaxFee,\r\n        uint16 defaultMaxGain,\r\n        uint16 defaultMaxLoss\r\n    ) internal virtual {\r\n        // Check for threshold and limit conditions.\r\n        require(\r\n            defaultManagement <= MANAGEMENT_FEE_THRESHOLD,\r\n            \"management fee threshold\"\r\n        );\r\n        require(\r\n            defaultPerformance <= PERFORMANCE_FEE_THRESHOLD,\r\n            \"performance fee threshold\"\r\n        );\r\n        require(defaultMaxLoss <= MAX_BPS, \"too high\");\r\n\r\n        // Update the default fee configuration.\r\n        defaultConfig = Fee({\r\n            managementFee: defaultManagement,\r\n            performanceFee: defaultPerformance,\r\n            refundRatio: defaultRefund,\r\n            maxFee: defaultMaxFee,\r\n            maxGain: defaultMaxGain,\r\n            maxLoss: defaultMaxLoss,\r\n            custom: false\r\n        });\r\n\r\n        emit UpdateDefaultFeeConfig(defaultConfig);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to set a custom fee configuration for a specific vault.\r\n     * @param vault The vault the strategy is hooked up to.\r\n     * @param customManagement Custom annual management fee to charge.\r\n     * @param customPerformance Custom performance fee to charge.\r\n     * @param customRefund Custom refund ratio to give back on losses.\r\n     * @param customMaxFee Custom max fee to allow as a percent of gain.\r\n     * @param customMaxGain Custom max percent gain a strategy can report.\r\n     * @param customMaxLoss Custom max percent loss a strategy can report.\r\n     */\r\n    function setCustomConfig(\r\n        address vault,\r\n        uint16 customManagement,\r\n        uint16 customPerformance,\r\n        uint16 customRefund,\r\n        uint16 customMaxFee,\r\n        uint16 customMaxGain,\r\n        uint16 customMaxLoss\r\n    ) external virtual onlyFeeManager {\r\n        // Ensure the vault has been added.\r\n        require(vaults[vault], \"vault not added\");\r\n        // Check for threshold and limit conditions.\r\n        require(\r\n            customManagement <= MANAGEMENT_FEE_THRESHOLD,\r\n            \"management fee threshold\"\r\n        );\r\n        require(\r\n            customPerformance <= PERFORMANCE_FEE_THRESHOLD,\r\n            \"performance fee threshold\"\r\n        );\r\n        require(customMaxLoss <= MAX_BPS, \"too high\");\r\n\r\n        // Create the vault's custom config.\r\n        Fee memory _config = Fee({\r\n            managementFee: customManagement,\r\n            performanceFee: customPerformance,\r\n            refundRatio: customRefund,\r\n            maxFee: customMaxFee,\r\n            maxGain: customMaxGain,\r\n            maxLoss: customMaxLoss,\r\n            custom: true\r\n        });\r\n\r\n        // Store the config.\r\n        customConfig[vault] = _config;\r\n\r\n        emit UpdateCustomFeeConfig(vault, _config);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to remove a previously set custom fee configuration for a vault.\r\n     * @param vault The vault to remove custom setting for.\r\n     */\r\n    function removeCustomConfig(address vault) external virtual onlyFeeManager {\r\n        // Ensure custom fees are set for the specified vault.\r\n        require(customConfig[vault].custom, \"No custom fees set\");\r\n\r\n        // Set all the vaults's custom fees to 0.\r\n        delete customConfig[vault];\r\n\r\n        // Emit relevant event.\r\n        emit RemovedCustomFeeConfig(vault);\r\n    }\r\n\r\n    /**\r\n     * @notice Turn off the health check for a specific `vault` `strategy` combo.\r\n     * @dev This will only last for one report and get automatically turned back on.\r\n     * @param vault Address of the vault.\r\n     * @param strategy Address of the strategy.\r\n     */\r\n    function turnOffHealthCheck(\r\n        address vault,\r\n        address strategy\r\n    ) external virtual onlyFeeManager {\r\n        // Ensure the vault has been added.\r\n        require(vaults[vault], \"vault not added\");\r\n\r\n        skipHealthCheck[vault][strategy] = true;\r\n    }\r\n\r\n    /**\r\n     * @notice Public getter to check for custom setting.\r\n     * @dev We use uint256 for the flag since its cheaper so this\r\n     *   will convert it to a bool for easy view functions.\r\n     *\r\n     * @param vault Address of the vault.\r\n     * @return If a custom fee config is set.\r\n     */\r\n    function useCustomConfig(\r\n        address vault\r\n    ) external view virtual returns (bool) {\r\n        return customConfig[vault].custom;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the full config used for a specific `vault`.\r\n     * @param vault Address of the vault.\r\n     * @return fee The config that would be used during the report.\r\n     */\r\n    function getVaultConfig(\r\n        address vault\r\n    ) external view returns (Fee memory fee) {\r\n        fee = customConfig[vault];\r\n\r\n        // Check if there is a custom config to use.\r\n        if (!fee.custom) {\r\n            // Otherwise use the default.\r\n            fee = defaultConfig;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Function to redeem the underlying asset from a vault.\r\n     * @dev Will default to using the full balance of the vault.\r\n     * @param vault The vault to redeem from.\r\n     */\r\n    function redeemUnderlying(address vault) external virtual {\r\n        redeemUnderlying(vault, IVault(vault).balanceOf(address(this)));\r\n    }\r\n\r\n    /**\r\n     * @notice Function to redeem the underlying asset from a vault.\r\n     * @param vault The vault to redeem from.\r\n     * @param amount The amount in vault shares to redeem.\r\n     */\r\n    function redeemUnderlying(\r\n        address vault,\r\n        uint256 amount\r\n    ) public virtual onlyFeeManager {\r\n        IVault(vault).redeem(amount, address(this), address(this), maxLoss);\r\n    }\r\n\r\n    /**\r\n     * @notice Sets the `maxLoss` parameter to be used on redeems.\r\n     * @param _maxLoss The amount in basis points to set as the maximum loss.\r\n     */\r\n    function setMaxLoss(uint256 _maxLoss) external virtual onlyFeeManager {\r\n        // Ensure that the provided `maxLoss` does not exceed 100% (in basis points).\r\n        require(_maxLoss <= MAX_BPS, \"higher than 100%\");\r\n\r\n        maxLoss = _maxLoss;\r\n\r\n        // Emit an event to signal the update of the `maxLoss` parameter.\r\n        emit UpdateMaxLoss(_maxLoss);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to distribute all accumulated fees to the designated recipient.\r\n     * @param token The token to distribute.\r\n     */\r\n    function distribute(address token) external virtual {\r\n        distribute(token, ERC20(token).balanceOf(address(this)));\r\n    }\r\n\r\n    /**\r\n     * @notice Function to distribute accumulated fees to the designated recipient.\r\n     * @param token The token to distribute.\r\n     * @param amount amount of token to distribute.\r\n     */\r\n    function distribute(\r\n        address token,\r\n        uint256 amount\r\n    ) public virtual onlyFeeManagerOrRecipient {\r\n        ERC20(token).safeTransfer(feeRecipient, amount);\r\n\r\n        emit DistributeRewards(token, amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to set a future fee manager address.\r\n     * @param _futureFeeManager The address to set as the future fee manager.\r\n     */\r\n    function setFutureFeeManager(\r\n        address _futureFeeManager\r\n    ) external virtual onlyFeeManager {\r\n        // Ensure the futureFeeManager is not a zero address.\r\n        require(_futureFeeManager != address(0), \"ZERO ADDRESS\");\r\n        futureFeeManager = _futureFeeManager;\r\n\r\n        emit SetFutureFeeManager(_futureFeeManager);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to accept the role change and become the new fee manager.\r\n     * @dev This function allows the future fee manager to accept the role change and become the new fee manager.\r\n     */\r\n    function acceptFeeManager() external virtual {\r\n        // Make sure the sender is the future fee manager.\r\n        require(msg.sender == futureFeeManager, \"not future fee manager\");\r\n        feeManager = futureFeeManager;\r\n        futureFeeManager = address(0);\r\n\r\n        emit NewFeeManager(msg.sender);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to set a new vault manager.\r\n     * @param newVaultManager Address to add or remove vaults.\r\n     */\r\n    function setVaultManager(\r\n        address newVaultManager\r\n    ) external virtual onlyFeeManager {\r\n        vaultManager = newVaultManager;\r\n\r\n        emit UpdateVaultManager(newVaultManager);\r\n    }\r\n\r\n    /**\r\n     * @notice Function to set a new address to receive distributed rewards.\r\n     * @param newFeeRecipient Address to receive distributed fees.\r\n     */\r\n    function setFeeRecipient(\r\n        address newFeeRecipient\r\n    ) external virtual onlyFeeManager {\r\n        // Ensure the newFeeRecipient is not a zero address.\r\n        require(newFeeRecipient != address(0), \"ZERO ADDRESS\");\r\n        address oldRecipient = feeRecipient;\r\n        feeRecipient = newFeeRecipient;\r\n\r\n        emit UpdateFeeRecipient(oldRecipient, newFeeRecipient);\r\n    }\r\n\r\n    /**\r\n     * @dev Internal safe function to make sure the contract you want to\r\n     * interact with has enough allowance to pull the desired tokens.\r\n     *\r\n     * @param _contract The address of the contract that will move the token.\r\n     * @param _token The ERC-20 token that will be getting spent.\r\n     * @param _amount The amount of `_token` to be spent.\r\n     */\r\n    function _checkAllowance(\r\n        address _contract,\r\n        address _token,\r\n        uint256 _amount\r\n    ) internal {\r\n        if (ERC20(_token).allowance(address(this), _contract) < _amount) {\r\n            ERC20(_token).safeApprove(_contract, 0);\r\n            ERC20(_token).safeApprove(_contract, _amount);\r\n        }\r\n    }\r\n}\r\n\r\n// prettier-ignore\r\nlibrary Roles {\r\n    uint256 internal constant ADD_STRATEGY_MANAGER             = 1;\r\n    uint256 internal constant REVOKE_STRATEGY_MANAGER          = 2;\r\n    uint256 internal constant FORCE_REVOKE_MANAGER             = 4;\r\n    uint256 internal constant ACCOUNTANT_MANAGER               = 8;\r\n    uint256 internal constant QUEUE_MANAGER                   = 16;\r\n    uint256 internal constant REPORTING_MANAGER               = 32;\r\n    uint256 internal constant DEBT_MANAGER                    = 64;\r\n    uint256 internal constant MAX_DEBT_MANAGER               = 128;\r\n    uint256 internal constant DEPOSIT_LIMIT_MANAGER          = 256;\r\n    uint256 internal constant WITHDRAW_LIMIT_MANAGER         = 512;\r\n    uint256 internal constant MINIMUM_IDLE_MANAGER          = 1024;\r\n    uint256 internal constant PROFIT_UNLOCK_MANAGER         = 2048;\r\n    uint256 internal constant DEBT_PURCHASER                = 4096;\r\n    uint256 internal constant EMERGENCY_MANAGER             = 8192;\r\n    uint256 internal constant ALL                          = 16383;\r\n}\r\n\r\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\r\n\r\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\r\n\r\n/**\r\n * @dev Standard signed math utilities missing in the Solidity language.\r\n */\r\nlibrary SignedMath {\r\n    /**\r\n     * @dev Returns the largest of two signed numbers.\r\n     */\r\n    function max(int256 a, int256 b) internal pure returns (int256) {\r\n        return a > b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the smallest of two signed numbers.\r\n     */\r\n    function min(int256 a, int256 b) internal pure returns (int256) {\r\n        return a < b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the average of two signed numbers without overflow.\r\n     * The result is rounded towards zero.\r\n     */\r\n    function average(int256 a, int256 b) internal pure returns (int256) {\r\n        // Formula from the book \"Hacker's Delight\"\r\n        int256 x = (a & b) + ((a ^ b) >> 1);\r\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the absolute unsigned value of a signed value.\r\n     */\r\n    function abs(int256 n) internal pure returns (uint256) {\r\n        unchecked {\r\n            // must be unchecked in order to support `n = type(int256).min`\r\n            return uint256(n >= 0 ? n : -n);\r\n        }\r\n    }\r\n}\r\n\r\n/**\r\n * @dev String operations.\r\n */\r\nlibrary Strings {\r\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\r\n    uint8 private constant _ADDRESS_LENGTH = 20;\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\r\n     */\r\n    function toString(uint256 value) internal pure returns (string memory) {\r\n        unchecked {\r\n            uint256 length = Math.log10(value) + 1;\r\n            string memory buffer = new string(length);\r\n            uint256 ptr;\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                ptr := add(buffer, add(32, length))\r\n            }\r\n            while (true) {\r\n                ptr--;\r\n                /// @solidity memory-safe-assembly\r\n                assembly {\r\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\r\n                }\r\n                value /= 10;\r\n                if (value == 0) break;\r\n            }\r\n            return buffer;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\r\n     */\r\n    function toString(int256 value) internal pure returns (string memory) {\r\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\r\n     */\r\n    function toHexString(uint256 value) internal pure returns (string memory) {\r\n        unchecked {\r\n            return toHexString(value, Math.log256(value) + 1);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\r\n     */\r\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\r\n        bytes memory buffer = new bytes(2 * length + 2);\r\n        buffer[0] = \"0\";\r\n        buffer[1] = \"x\";\r\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\r\n            buffer[i] = _SYMBOLS[value & 0xf];\r\n            value >>= 4;\r\n        }\r\n        require(value == 0, \"Strings: hex length insufficient\");\r\n        return string(buffer);\r\n    }\r\n\r\n    /**\r\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\r\n     */\r\n    function toHexString(address addr) internal pure returns (string memory) {\r\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if the two strings are equal.\r\n     */\r\n    function equal(string memory a, string memory b) internal pure returns (bool) {\r\n        return keccak256(bytes(a)) == keccak256(bytes(b));\r\n    }\r\n}\r\n\r\ncontract Governance2Step is Governance {\r\n    /// @notice Emitted when the pending governance address is set.\r\n    event UpdatePendingGovernance(address indexed newPendingGovernance);\r\n\r\n    /// @notice Address that is set to take over governance.\r\n    address public pendingGovernance;\r\n\r\n    constructor(address _governance) Governance(_governance) {}\r\n\r\n    /**\r\n     * @notice Sets a new address as the `pendingGovernance` of the contract.\r\n     * @dev Throws if the caller is not current governance.\r\n     * @param _newGovernance The new governance address.\r\n     */\r\n    function transferGovernance(\r\n        address _newGovernance\r\n    ) external virtual override onlyGovernance {\r\n        require(_newGovernance != address(0), \"ZERO ADDRESS\");\r\n        pendingGovernance = _newGovernance;\r\n\r\n        emit UpdatePendingGovernance(_newGovernance);\r\n    }\r\n\r\n    /**\r\n     * @notice Allows the `pendingGovernance` to accept the role.\r\n     */\r\n    function acceptGovernance() external virtual {\r\n        require(msg.sender == pendingGovernance, \"!pending governance\");\r\n\r\n        emit GovernanceTransferred(governance, msg.sender);\r\n\r\n        governance = msg.sender;\r\n        pendingGovernance = address(0);\r\n    }\r\n}\r\n\r\n/**\r\n * @title YearnV3 Debt Allocator\r\n * @author yearn.finance\r\n * @notice\r\n *  This Debt Allocator is meant to be used alongside\r\n *  a Yearn V3 vault to provide the needed triggers for a keeper\r\n *  to perform automated debt updates for the vaults strategies.\r\n *\r\n *  Each allocator contract will serve one Vault and each strategy\r\n *  that should be managed by this allocator will need to be added\r\n *  manually by setting a `targetRatio` and `maxRatio`.\r\n *\r\n *  The allocator aims to allocate debt between the strategies\r\n *  based on their set target ratios. Which are denominated in basis\r\n *  points and represent the percent of total assets that specific\r\n *  strategy should hold.\r\n *\r\n *  The trigger will attempt to allocate up to the `maxRatio` when\r\n *  the strategy has `minimumChange` amount less than the `targetRatio`.\r\n *  And will pull funds from the strategy when it has `minimumChange`\r\n *  more than its `maxRatio`.\r\n */\r\ncontract DebtAllocator {\r\n    /// @notice An event emitted when a strategies debt ratios are Updated.\r\n    event UpdateStrategyDebtRatio(\r\n        address indexed strategy,\r\n        uint256 newTargetRatio,\r\n        uint256 newMaxRatio,\r\n        uint256 newTotalDebtRatio\r\n    );\r\n\r\n    /// @notice An event emitted when a strategy is added or removed.\r\n    event StrategyChanged(address indexed strategy, Status status);\r\n\r\n    /// @notice An event emitted when the minimum time to wait is updated.\r\n    event UpdateMinimumWait(uint256 newMinimumWait);\r\n\r\n    /// @notice An event emitted when the minimum change is updated.\r\n    event UpdateMinimumChange(uint256 newMinimumChange);\r\n\r\n    /// @notice An event emitted when a keeper is added or removed.\r\n    event UpdateManager(address indexed manager, bool allowed);\r\n\r\n    /// @notice An event emitted when the max debt update loss is updated.\r\n    event UpdateMaxDebtUpdateLoss(uint256 newMaxDebtUpdateLoss);\r\n\r\n    /// @notice Status when a strategy is added or removed from the allocator.\r\n    enum Status {\r\n        NULL,\r\n        ADDED,\r\n        REMOVED\r\n    }\r\n\r\n    /// @notice Struct for each strategies info.\r\n    struct Config {\r\n        // Flag to set when a strategy is added.\r\n        bool added;\r\n        // The ideal percent in Basis Points the strategy should have.\r\n        uint16 targetRatio;\r\n        // The max percent of assets the strategy should hold.\r\n        uint16 maxRatio;\r\n        // Timestamp of the last time debt was updated.\r\n        // The debt updates must be done through this allocator\r\n        // for this to be used.\r\n        uint96 lastUpdate;\r\n        // We have an extra 120 bits in the slot.\r\n        // So we declare the variable in the struct so it can be\r\n        // used if this contract is inherited.\r\n        uint120 open;\r\n    }\r\n\r\n    /// @notice Make sure the caller is governance.\r\n    modifier onlyGovernance() {\r\n        _isGovernance();\r\n        _;\r\n    }\r\n\r\n    /// @notice Make sure the caller is governance or a manager.\r\n    modifier onlyManagers() {\r\n        _isManager();\r\n        _;\r\n    }\r\n\r\n    /// @notice Make sure the caller is a keeper\r\n    modifier onlyKeepers() {\r\n        _isKeeper();\r\n        _;\r\n    }\r\n\r\n    /// @notice Check the Factories governance address.\r\n    function _isGovernance() internal view virtual {\r\n        require(\r\n            msg.sender == DebtAllocatorFactory(factory).governance(),\r\n            \"!governance\"\r\n        );\r\n    }\r\n\r\n    /// @notice Check is either factories governance or local manager.\r\n    function _isManager() internal view virtual {\r\n        require(\r\n            managers[msg.sender] ||\r\n                msg.sender == DebtAllocatorFactory(factory).governance(),\r\n            \"!manager\"\r\n        );\r\n    }\r\n\r\n    /// @notice Check is one of the allowed keepers.\r\n    function _isKeeper() internal view virtual {\r\n        require(DebtAllocatorFactory(factory).keepers(msg.sender), \"!keeper\");\r\n    }\r\n\r\n    uint256 internal constant MAX_BPS = 10_000;\r\n\r\n    /// @notice Address to get permissioned roles from.\r\n    address public immutable factory;\r\n\r\n    /// @notice Address of the vault this serves as allocator for.\r\n    address public vault;\r\n\r\n    /// @notice Time to wait between debt updates in seconds.\r\n    uint256 public minimumWait;\r\n\r\n    /// @notice The minimum amount denominated in asset that will\r\n    // need to be moved to trigger a debt update.\r\n    uint256 public minimumChange;\r\n\r\n    /// @notice Total debt ratio currently allocated in basis points.\r\n    // Can't be more than 10_000.\r\n    uint256 public totalDebtRatio;\r\n\r\n    /// @notice Max loss to accept on debt updates in basis points.\r\n    uint256 public maxDebtUpdateLoss;\r\n\r\n    /// @notice Mapping of addresses that are allowed to update debt ratios.\r\n    mapping(address => bool) public managers;\r\n\r\n    /// @notice Mapping of strategy => its config.\r\n    mapping(address => Config) internal _configs;\r\n\r\n    constructor() {\r\n        // Set the factory to retrieve roles from. Will be the same for all clones so can use immutable.\r\n        factory = msg.sender;\r\n\r\n        // Don't allow for original version to be initialized.\r\n        vault = address(1);\r\n    }\r\n\r\n    /**\r\n     * @notice Initializes the debt allocator.\r\n     * @dev Should be called atomically after cloning.\r\n     * @param _vault Address of the vault this allocates debt for.\r\n     * @param _minimumChange The minimum in asset that must be moved.\r\n     */\r\n    function initialize(address _vault, uint256 _minimumChange) public virtual {\r\n        require(address(vault) == address(0), \"!initialized\");\r\n\r\n        // Set initial variables.\r\n        vault = _vault;\r\n        minimumChange = _minimumChange;\r\n\r\n        // Default max loss on debt updates to 1 BP.\r\n        maxDebtUpdateLoss = 1;\r\n    }\r\n\r\n    /**\r\n     * @notice Debt update wrapper for the vault.\r\n     * @dev This can be used if a minimum time between debt updates\r\n     *   is desired to be used for the trigger and to enforce a max loss.\r\n     *\r\n     *   This contract must have the DEBT_MANAGER role assigned to them.\r\n     *\r\n     *   The function signature matches the vault so no update to the\r\n     *   call data is required.\r\n     *\r\n     *   This will also run checks on losses realized during debt\r\n     *   updates to assure decreases did not realize profits outside\r\n     *   of the allowed range.\r\n     */\r\n    function update_debt(\r\n        address _strategy,\r\n        uint256 _targetDebt\r\n    ) public virtual onlyKeepers {\r\n        IVault _vault = IVault(vault);\r\n\r\n        // If going to 0 record full balance first.\r\n        if (_targetDebt == 0) {\r\n            _vault.process_report(_strategy);\r\n        }\r\n\r\n        // Update debt with the default max loss.\r\n        _vault.update_debt(_strategy, _targetDebt, maxDebtUpdateLoss);\r\n\r\n        // Update the last time the strategies debt was updated.\r\n        _configs[_strategy].lastUpdate = uint96(block.timestamp);\r\n    }\r\n\r\n    /**\r\n     * @notice Check if a strategy's debt should be updated.\r\n     * @dev This should be called by a keeper to decide if a strategies\r\n     * debt should be updated and if so by how much.\r\n     *\r\n     * @param _strategy Address of the strategy to check.\r\n     * @return . Bool representing if the debt should be updated.\r\n     * @return . Calldata if `true` or reason if `false`.\r\n     */\r\n    function shouldUpdateDebt(\r\n        address _strategy\r\n    ) public view virtual returns (bool, bytes memory) {\r\n        // Get the strategy specific debt config.\r\n        Config memory config = getConfig(_strategy);\r\n\r\n        // Make sure the strategy has been added to the allocator.\r\n        if (!config.added) return (false, bytes(\"!added\"));\r\n\r\n        // Check the base fee isn't too high.\r\n        if (!DebtAllocatorFactory(factory).isCurrentBaseFeeAcceptable()) {\r\n            return (false, bytes(\"Base Fee\"));\r\n        }\r\n\r\n        // Cache the vault variable.\r\n        IVault _vault = IVault(vault);\r\n        // Retrieve the strategy specific parameters.\r\n        IVault.StrategyParams memory params = _vault.strategies(_strategy);\r\n        // Make sure its an active strategy.\r\n        require(params.activation != 0, \"!active\");\r\n\r\n        if (block.timestamp - config.lastUpdate <= minimumWait) {\r\n            return (false, bytes(\"min wait\"));\r\n        }\r\n\r\n        uint256 vaultAssets = _vault.totalAssets();\r\n\r\n        // Get the target debt for the strategy based on vault assets.\r\n        uint256 targetDebt = Math.min(\r\n            (vaultAssets * config.targetRatio) / MAX_BPS,\r\n            // Make sure it is not more than the max allowed.\r\n            params.max_debt\r\n        );\r\n\r\n        // Get the max debt we would want the strategy to have.\r\n        uint256 maxDebt = Math.min(\r\n            (vaultAssets * config.maxRatio) / MAX_BPS,\r\n            // Make sure it is not more than the max allowed.\r\n            params.max_debt\r\n        );\r\n\r\n        // If we need to add more.\r\n        if (targetDebt > params.current_debt) {\r\n            uint256 currentIdle = _vault.totalIdle();\r\n            uint256 minIdle = _vault.minimum_total_idle();\r\n\r\n            // We can't add more than the available idle.\r\n            if (minIdle >= currentIdle) {\r\n                return (false, bytes(\"No Idle\"));\r\n            }\r\n\r\n            // Add up to the max if possible\r\n            uint256 toAdd = Math.min(\r\n                maxDebt - params.current_debt,\r\n                // Can't take more than is available.\r\n                Math.min(\r\n                    currentIdle - minIdle,\r\n                    IVault(_strategy).maxDeposit(vault)\r\n                )\r\n            );\r\n\r\n            // If the amount to add is over our threshold.\r\n            if (toAdd > minimumChange) {\r\n                // Return true and the calldata.\r\n                return (\r\n                    true,\r\n                    abi.encodeWithSignature(\r\n                        \"update_debt(address,uint256)\",\r\n                        _strategy,\r\n                        params.current_debt + toAdd\r\n                    )\r\n                );\r\n            }\r\n            // If current debt is greater than our max.\r\n        } else if (maxDebt < params.current_debt) {\r\n            uint256 toPull = params.current_debt - targetDebt;\r\n\r\n            uint256 currentIdle = _vault.totalIdle();\r\n            uint256 minIdle = _vault.minimum_total_idle();\r\n            if (minIdle > currentIdle) {\r\n                // Pull at least the amount needed for minIdle.\r\n                toPull = Math.max(toPull, minIdle - currentIdle);\r\n            }\r\n\r\n            // Find out by how much. Aim for the target.\r\n            toPull = Math.min(\r\n                toPull,\r\n                // Account for the current liquidity constraints.\r\n                // Use max redeem to match vault logic.\r\n                IVault(_strategy).convertToAssets(\r\n                    IVault(_strategy).maxRedeem(address(_vault))\r\n                )\r\n            );\r\n\r\n            // Check if it's over the threshold.\r\n            if (toPull > minimumChange) {\r\n                // Can't lower debt if there are unrealised losses.\r\n                if (\r\n                    _vault.assess_share_of_unrealised_losses(\r\n                        _strategy,\r\n                        params.current_debt\r\n                    ) != 0\r\n                ) {\r\n                    return (false, bytes(\"unrealised loss\"));\r\n                }\r\n\r\n                // If so return true and the calldata.\r\n                return (\r\n                    true,\r\n                    abi.encodeWithSignature(\r\n                        \"update_debt(address,uint256)\",\r\n                        _strategy,\r\n                        params.current_debt - toPull\r\n                    )\r\n                );\r\n            }\r\n        }\r\n\r\n        // Either no change or below our minimumChange.\r\n        return (false, bytes(\"Below Min\"));\r\n    }\r\n\r\n    /**\r\n     * @notice Increase a strategies target debt ratio.\r\n     * @dev `setStrategyDebtRatio` functions will do all needed checks.\r\n     * @param _strategy The address of the strategy to increase the debt ratio for.\r\n     * @param _increase The amount in Basis Points to increase it.\r\n     */\r\n    function increaseStrategyDebtRatio(\r\n        address _strategy,\r\n        uint256 _increase\r\n    ) external virtual {\r\n        uint256 _currentRatio = getConfig(_strategy).targetRatio;\r\n        setStrategyDebtRatio(_strategy, _currentRatio + _increase);\r\n    }\r\n\r\n    /**\r\n     * @notice Decrease a strategies target debt ratio.\r\n     * @param _strategy The address of the strategy to decrease the debt ratio for.\r\n     * @param _decrease The amount in Basis Points to decrease it.\r\n     */\r\n    function decreaseStrategyDebtRatio(\r\n        address _strategy,\r\n        uint256 _decrease\r\n    ) external virtual {\r\n        uint256 _currentRatio = getConfig(_strategy).targetRatio;\r\n        setStrategyDebtRatio(_strategy, _currentRatio - _decrease);\r\n    }\r\n\r\n    /**\r\n     * @notice Sets a new target debt ratio for a strategy.\r\n     * @dev This will default to a 20% increase for max debt.\r\n     *\r\n     * @param _strategy Address of the strategy to set.\r\n     * @param _targetRatio Amount in Basis points to allocate.\r\n     */\r\n    function setStrategyDebtRatio(\r\n        address _strategy,\r\n        uint256 _targetRatio\r\n    ) public virtual {\r\n        uint256 maxRatio = Math.min((_targetRatio * 12_000) / MAX_BPS, MAX_BPS);\r\n        setStrategyDebtRatio(_strategy, _targetRatio, maxRatio);\r\n    }\r\n\r\n    /**\r\n     * @notice Sets a new target debt ratio for a strategy.\r\n     * @dev A `minimumChange` for that strategy must be set first.\r\n     * This is to prevent debt from being updated too frequently.\r\n     *\r\n     * @param _strategy Address of the strategy to set.\r\n     * @param _targetRatio Amount in Basis points to allocate.\r\n     * @param _maxRatio Max ratio to give on debt increases.\r\n     */\r\n    function setStrategyDebtRatio(\r\n        address _strategy,\r\n        uint256 _targetRatio,\r\n        uint256 _maxRatio\r\n    ) public virtual onlyManagers {\r\n        // Make sure a minimumChange has been set.\r\n        require(minimumChange != 0, \"!minimum\");\r\n        // Cannot be more than 100%.\r\n        require(_maxRatio <= MAX_BPS, \"max too high\");\r\n        // Max cannot be lower than the target.\r\n        require(_maxRatio >= _targetRatio, \"max ratio\");\r\n\r\n        // Get the current config.\r\n        Config memory config = getConfig(_strategy);\r\n\r\n        // Set added flag if not set yet.\r\n        if (!config.added) {\r\n            config.added = true;\r\n            emit StrategyChanged(_strategy, Status.ADDED);\r\n        }\r\n\r\n        // Get what will be the new total debt ratio.\r\n        uint256 newTotalDebtRatio = totalDebtRatio -\r\n            config.targetRatio +\r\n            _targetRatio;\r\n\r\n        // Make sure it is under 100% allocated\r\n        require(newTotalDebtRatio <= MAX_BPS, \"ratio too high\");\r\n\r\n        // Update local config.\r\n        config.targetRatio = uint16(_targetRatio);\r\n        config.maxRatio = uint16(_maxRatio);\r\n\r\n        // Write to storage.\r\n        _configs[_strategy] = config;\r\n        totalDebtRatio = newTotalDebtRatio;\r\n\r\n        emit UpdateStrategyDebtRatio(\r\n            _strategy,\r\n            _targetRatio,\r\n            _maxRatio,\r\n            newTotalDebtRatio\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Remove a strategy from this debt allocator.\r\n     * @dev Will delete the full config for the strategy\r\n     * @param _strategy Address of the address ro remove.\r\n     */\r\n    function removeStrategy(address _strategy) external virtual onlyManagers {\r\n        Config memory config = getConfig(_strategy);\r\n        require(config.added, \"!added\");\r\n\r\n        uint256 target = config.targetRatio;\r\n\r\n        // Remove any debt ratio the strategy holds.\r\n        if (target != 0) {\r\n            totalDebtRatio -= target;\r\n            emit UpdateStrategyDebtRatio(_strategy, 0, 0, totalDebtRatio);\r\n        }\r\n\r\n        // Remove the full config including the `added` flag.\r\n        delete _configs[_strategy];\r\n\r\n        // Emit Event.\r\n        emit StrategyChanged(_strategy, Status.REMOVED);\r\n    }\r\n\r\n    /**\r\n     * @notice Set the minimum change variable for a strategy.\r\n     * @dev This is the minimum amount of debt to be\r\n     * added or pulled for it to trigger an update.\r\n     *\r\n     * @param _minimumChange The new minimum to set for the strategy.\r\n     */\r\n    function setMinimumChange(\r\n        uint256 _minimumChange\r\n    ) external virtual onlyGovernance {\r\n        require(_minimumChange > 0, \"zero\");\r\n        // Set the new minimum.\r\n        minimumChange = _minimumChange;\r\n\r\n        emit UpdateMinimumChange(_minimumChange);\r\n    }\r\n\r\n    /**\r\n     * @notice Set the max loss in Basis points to allow on debt updates.\r\n     * @dev Withdrawing during debt updates use {redeem} which allows for 100% loss.\r\n     *      This can be used to assure a loss is not realized on redeem outside the tolerance.\r\n     * @param _maxDebtUpdateLoss The max loss to accept on debt updates.\r\n     */\r\n    function setMaxDebtUpdateLoss(\r\n        uint256 _maxDebtUpdateLoss\r\n    ) external virtual onlyGovernance {\r\n        require(_maxDebtUpdateLoss <= MAX_BPS, \"higher than max\");\r\n        maxDebtUpdateLoss = _maxDebtUpdateLoss;\r\n\r\n        emit UpdateMaxDebtUpdateLoss(_maxDebtUpdateLoss);\r\n    }\r\n\r\n    /**\r\n     * @notice Set the minimum time to wait before re-updating a strategies debt.\r\n     * @dev This is only enforced per strategy.\r\n     * @param _minimumWait The minimum time in seconds to wait.\r\n     */\r\n    function setMinimumWait(\r\n        uint256 _minimumWait\r\n    ) external virtual onlyGovernance {\r\n        minimumWait = _minimumWait;\r\n\r\n        emit UpdateMinimumWait(_minimumWait);\r\n    }\r\n\r\n    /**\r\n     * @notice Set if a manager can update ratios.\r\n     * @param _address The address to set mapping for.\r\n     * @param _allowed If the address can call {update_debt}.\r\n     */\r\n    function setManager(\r\n        address _address,\r\n        bool _allowed\r\n    ) external virtual onlyGovernance {\r\n        managers[_address] = _allowed;\r\n\r\n        emit UpdateManager(_address, _allowed);\r\n    }\r\n\r\n    /**\r\n     * @notice Get a strategies full config.\r\n     * @dev Used for customizations by inheriting the contract.\r\n     * @param _strategy Address of the strategy.\r\n     * @return The strategies current Config.\r\n     */\r\n    function getConfig(\r\n        address _strategy\r\n    ) public view virtual returns (Config memory) {\r\n        return _configs[_strategy];\r\n    }\r\n\r\n    /**\r\n     * @notice Get a strategies target debt ratio.\r\n     * @param _strategy Address of the strategy.\r\n     * @return The strategies current targetRatio.\r\n     */\r\n    function getStrategyTargetRatio(\r\n        address _strategy\r\n    ) external view virtual returns (uint256) {\r\n        return getConfig(_strategy).targetRatio;\r\n    }\r\n\r\n    /**\r\n     * @notice Get a strategies max debt ratio.\r\n     * @param _strategy Address of the strategy.\r\n     * @return The strategies current maxRatio.\r\n     */\r\n    function getStrategyMaxRatio(\r\n        address _strategy\r\n    ) external view virtual returns (uint256) {\r\n        return getConfig(_strategy).maxRatio;\r\n    }\r\n}\r\n\r\ncontract Clonable {\r\n    /// @notice Set to the address to auto clone from.\r\n    address public original;\r\n\r\n    /**\r\n     * @notice Clone the contracts default `original` contract.\r\n     * @return Address of the new Minimal Proxy clone.\r\n     */\r\n    function _clone() internal virtual returns (address) {\r\n        return _clone(original);\r\n    }\r\n\r\n    /**\r\n     * @notice Clone any `_original` contract.\r\n     * @return _newContract Address of the new Minimal Proxy clone.\r\n     */\r\n    function _clone(\r\n        address _original\r\n    ) internal virtual returns (address _newContract) {\r\n        // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol\r\n        bytes20 addressBytes = bytes20(_original);\r\n        assembly {\r\n            // EIP-1167 bytecode\r\n            let clone_code := mload(0x40)\r\n            mstore(\r\n                clone_code,\r\n                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000\r\n            )\r\n            mstore(add(clone_code, 0x14), addressBytes)\r\n            mstore(\r\n                add(clone_code, 0x28),\r\n                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000\r\n            )\r\n            _newContract := create(0, clone_code, 0x37)\r\n        }\r\n    }\r\n}\r\n\r\ninterface IBaseFee {\r\n    function basefee_global() external view returns (uint256);\r\n}\r\n\r\n/**\r\n * @title YearnV3  Debt Allocator Factory\r\n * @author yearn.finance\r\n * @notice\r\n *  Factory to deploy a debt allocator for a YearnV3 vault.\r\n */\r\ncontract DebtAllocatorFactory is Governance, Clonable {\r\n    /// @notice Revert message for when a debt allocator already exists.\r\n    error AlreadyDeployed(address _allocator);\r\n\r\n    /// @notice An event emitted when the base fee provider is set.\r\n    event UpdatedBaseFeeProvider(address baseFeeProvider);\r\n\r\n    /// @notice An event emitted when a keeper is added or removed.\r\n    event UpdateKeeper(address indexed keeper, bool allowed);\r\n\r\n    /// @notice An event emitted when the max base fee is updated.\r\n    event UpdateMaxAcceptableBaseFee(uint256 newMaxAcceptableBaseFee);\r\n\r\n    /// @notice An event emitted when a new debt allocator is added or deployed.\r\n    event NewDebtAllocator(address indexed allocator, address indexed vault);\r\n\r\n    /// @notice Provider to read current block's base fee.\r\n    address public baseFeeProvider;\r\n\r\n    /// @notice Max the chains base fee can be during debt update.\r\n    // Will default to max uint256 and need to be set to be used.\r\n    uint256 public maxAcceptableBaseFee;\r\n\r\n    /// @notice Mapping of addresses that are allowed to update debt.\r\n    mapping(address => bool) public keepers;\r\n\r\n    constructor(address _governance) Governance(_governance) {\r\n        // Deploy a dummy allocator as the original.\r\n        original = address(new DebtAllocator());\r\n\r\n        // Default max base fee to uint max.\r\n        maxAcceptableBaseFee = type(uint256).max;\r\n\r\n        // Default to allow governance to be a keeper.\r\n        keepers[_governance] = true;\r\n        emit UpdateKeeper(_governance, true);\r\n    }\r\n\r\n    /**\r\n     * @notice Clones a new debt allocator.\r\n     * @dev defaults to msg.sender as the governance role and 0\r\n     *  for the `minimumChange`.\r\n     *\r\n     * @param _vault The vault for the allocator to be hooked to.\r\n     * @return Address of the new debt allocator\r\n     */\r\n    function newDebtAllocator(\r\n        address _vault\r\n    ) external virtual returns (address) {\r\n        return newDebtAllocator(_vault, 0);\r\n    }\r\n\r\n    /**\r\n     * @notice Clones a new debt allocator.\r\n     * @param _vault The vault for the allocator to be hooked to.\r\n     * @param _minimumChange The minimum amount needed to trigger debt update.\r\n     * @return newAllocator Address of the new debt allocator\r\n     */\r\n    function newDebtAllocator(\r\n        address _vault,\r\n        uint256 _minimumChange\r\n    ) public virtual returns (address newAllocator) {\r\n        // Clone new allocator off the original.\r\n        newAllocator = _clone();\r\n\r\n        // Initialize the new allocator.\r\n        DebtAllocator(newAllocator).initialize(_vault, _minimumChange);\r\n\r\n        // Emit event.\r\n        emit NewDebtAllocator(newAllocator, _vault);\r\n    }\r\n\r\n    /**\r\n     * @notice\r\n     *  Used to set our baseFeeProvider, which checks the network's current base\r\n     *  fee price to determine whether it is an optimal time to harvest or tend.\r\n     *\r\n     *  This may only be called by governance.\r\n     * @param _baseFeeProvider Address of our baseFeeProvider\r\n     */\r\n    function setBaseFeeOracle(\r\n        address _baseFeeProvider\r\n    ) external virtual onlyGovernance {\r\n        baseFeeProvider = _baseFeeProvider;\r\n\r\n        emit UpdatedBaseFeeProvider(_baseFeeProvider);\r\n    }\r\n\r\n    /**\r\n     * @notice Set the max acceptable base fee.\r\n     * @dev This defaults to max uint256 and will need to\r\n     * be set for it to be used.\r\n     *\r\n     * Is denominated in gwei. So 50gwei would be set as 50e9.\r\n     *\r\n     * @param _maxAcceptableBaseFee The new max base fee.\r\n     */\r\n    function setMaxAcceptableBaseFee(\r\n        uint256 _maxAcceptableBaseFee\r\n    ) external virtual onlyGovernance {\r\n        maxAcceptableBaseFee = _maxAcceptableBaseFee;\r\n\r\n        emit UpdateMaxAcceptableBaseFee(_maxAcceptableBaseFee);\r\n    }\r\n\r\n    /**\r\n     * @notice Set if a keeper can update debt.\r\n     * @param _address The address to set mapping for.\r\n     * @param _allowed If the address can call {update_debt}.\r\n     */\r\n    function setKeeper(\r\n        address _address,\r\n        bool _allowed\r\n    ) external virtual onlyGovernance {\r\n        keepers[_address] = _allowed;\r\n\r\n        emit UpdateKeeper(_address, _allowed);\r\n    }\r\n\r\n    /**\r\n     * @notice Returns wether or not the current base fee is acceptable\r\n     *   based on the `maxAcceptableBaseFee`.\r\n     * @return . If the current base fee is acceptable.\r\n     */\r\n    function isCurrentBaseFeeAcceptable() external view virtual returns (bool) {\r\n        address _baseFeeProvider = baseFeeProvider;\r\n        if (_baseFeeProvider == address(0)) return true;\r\n        return\r\n            maxAcceptableBaseFee >= IBaseFee(_baseFeeProvider).basefee_global();\r\n    }\r\n}\r\n\r\n/// @title Yearn V3 Vault Role Manager.\r\ncontract RoleManager is Governance2Step {\r\n    /// @notice Revert message for when a vault has already been deployed.\r\n    error AlreadyDeployed(address _vault);\r\n\r\n    /// @notice Emitted when a new vault has been deployed or added.\r\n    event AddedNewVault(\r\n        address indexed vault,\r\n        address indexed debtAllocator,\r\n        uint256 category\r\n    );\r\n\r\n    /// @notice Emitted when a vaults debt allocator is updated.\r\n    event UpdateDebtAllocator(\r\n        address indexed vault,\r\n        address indexed debtAllocator\r\n    );\r\n\r\n    /// @notice Emitted when a new address is set for a position.\r\n    event UpdatePositionHolder(\r\n        bytes32 indexed position,\r\n        address indexed newAddress\r\n    );\r\n\r\n    /// @notice Emitted when a vault is removed.\r\n    event RemovedVault(address indexed vault);\r\n\r\n    /// @notice Emitted when a new set of roles is set for a position\r\n    event UpdatePositionRoles(bytes32 indexed position, uint256 newRoles);\r\n\r\n    /// @notice Emitted when the defaultProfitMaxUnlock variable is updated.\r\n    event UpdateDefaultProfitMaxUnlock(uint256 newDefaultProfitMaxUnlock);\r\n\r\n    /// @notice Position struct\r\n    struct Position {\r\n        address holder;\r\n        uint96 roles;\r\n    }\r\n\r\n    /// @notice Config that holds all vault info.\r\n    struct VaultConfig {\r\n        address asset;\r\n        uint256 category;\r\n        address debtAllocator;\r\n        uint256 index;\r\n    }\r\n\r\n    /// @notice Only allow either governance or the position holder to call.\r\n    modifier onlyPositionHolder(bytes32 _positionId) {\r\n        _isPositionHolder(_positionId);\r\n        _;\r\n    }\r\n\r\n    /// @notice Check if the msg sender is governance or the specified position holder.\r\n    function _isPositionHolder(bytes32 _positionId) internal view virtual {\r\n        require(\r\n            msg.sender == governance ||\r\n                msg.sender == getPositionHolder(_positionId),\r\n            \"!allowed\"\r\n        );\r\n    }\r\n\r\n    // Encoded name so that it can be held as a constant.\r\n    bytes32 internal constant _name_ =\r\n        bytes32(abi.encodePacked(\"Yearn V3 Vault Role Manager\"));\r\n\r\n    /*//////////////////////////////////////////////////////////////\r\n                           POSITION ID'S\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    /// @notice Position ID for \"daddy\".\r\n    bytes32 public constant DADDY = keccak256(\"Daddy\");\r\n    /// @notice Position ID for \"brain\".\r\n    bytes32 public constant BRAIN = keccak256(\"Brain\");\r\n    /// @notice Position ID for \"keeper\".\r\n    bytes32 public constant KEEPER = keccak256(\"Keeper\");\r\n    /// @notice Position ID for \"security\".\r\n    bytes32 public constant SECURITY = keccak256(\"Security\");\r\n    /// @notice Position ID for the Registry.\r\n    bytes32 public constant REGISTRY = keccak256(\"Registry\");\r\n    /// @notice Position ID for the Accountant.\r\n    bytes32 public constant ACCOUNTANT = keccak256(\"Accountant\");\r\n    /// @notice Position ID for Debt Allocator\r\n    bytes32 public constant DEBT_ALLOCATOR = keccak256(\"Debt Allocator\");\r\n    /// @notice Position ID for Strategy manager.\r\n    bytes32 public constant STRATEGY_MANAGER = keccak256(\"Strategy Manager\");\r\n    /// @notice Position ID for the Allocator Factory.\r\n    bytes32 public constant ALLOCATOR_FACTORY = keccak256(\"Allocator Factory\");\r\n\r\n    /// @notice Immutable address that the RoleManager position\r\n    // will be transferred to when a vault is removed.\r\n    address public immutable chad;\r\n\r\n    /*//////////////////////////////////////////////////////////////\r\n                           STORAGE\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    /// @notice Array storing addresses of all managed vaults.\r\n    address[] public vaults;\r\n\r\n    /// @notice Default time until profits are fully unlocked for new vaults.\r\n    uint256 public defaultProfitMaxUnlock = 10 days;\r\n\r\n    /// @notice Mapping of position ID to position information.\r\n    mapping(bytes32 => Position) internal _positions;\r\n    /// @notice Mapping of vault addresses to its config.\r\n    mapping(address => VaultConfig) public vaultConfig;\r\n    /// @notice Mapping of underlying asset, api version and category to vault.\r\n    mapping(address => mapping(string => mapping(uint256 => address)))\r\n        internal _assetToVault;\r\n\r\n    constructor(\r\n        address _governance,\r\n        address _daddy,\r\n        address _brain,\r\n        address _security,\r\n        address _keeper,\r\n        address _strategyManager,\r\n        address _registry\r\n    ) Governance2Step(_governance) {\r\n        require(_daddy != address(0), \"ZERO ADDRESS\");\r\n        // Set the immutable address that will take over role manager\r\n        // if a vault is removed.\r\n        chad = _daddy;\r\n\r\n        // Set up the initial role configs for each position.\r\n\r\n        // Daddy is given all of the roles.\r\n        _positions[DADDY] = Position({\r\n            holder: _daddy,\r\n            roles: uint96(Roles.ALL)\r\n        });\r\n\r\n        // Setup default roles for Brain.\r\n        _positions[BRAIN] = Position({\r\n            holder: _brain,\r\n            roles: uint96(\r\n                Roles.REPORTING_MANAGER |\r\n                    Roles.DEBT_MANAGER |\r\n                    Roles.QUEUE_MANAGER |\r\n                    Roles.DEPOSIT_LIMIT_MANAGER |\r\n                    Roles.DEBT_PURCHASER\r\n            )\r\n        });\r\n\r\n        // Security can set the max debt for strategies to have.\r\n        _positions[SECURITY] = Position({\r\n            holder: _security,\r\n            roles: uint96(Roles.MAX_DEBT_MANAGER)\r\n        });\r\n\r\n        // The keeper can process reports.\r\n        _positions[KEEPER] = Position({\r\n            holder: _keeper,\r\n            roles: uint96(Roles.REPORTING_MANAGER)\r\n        });\r\n\r\n        // Debt allocators manage debt and also need to process reports.\r\n        _positions[DEBT_ALLOCATOR].roles = uint96(\r\n            Roles.REPORTING_MANAGER | Roles.DEBT_MANAGER\r\n        );\r\n\r\n        // The strategy manager can add and remove strategies.\r\n        _positions[STRATEGY_MANAGER] = Position({\r\n            holder: _strategyManager,\r\n            roles: uint96(\r\n                Roles.ADD_STRATEGY_MANAGER | Roles.REVOKE_STRATEGY_MANAGER\r\n            )\r\n        });\r\n\r\n        // Set the registry\r\n        _positions[REGISTRY].holder = _registry;\r\n    }\r\n\r\n    /*//////////////////////////////////////////////////////////////\r\n                           VAULT CREATION\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    /**\r\n     * @notice Creates a new endorsed vault with default profit max\r\n     *      unlock time and doesn't set the deposit limit.\r\n     * @param _asset Address of the underlying asset.\r\n     * @param _category Category of the vault.\r\n     * @return _vault Address of the newly created vault.\r\n     */\r\n    function newVault(\r\n        address _asset,\r\n        uint256 _category\r\n    ) external virtual onlyPositionHolder(DADDY) returns (address) {\r\n        return _newVault(_asset, _category, 0, defaultProfitMaxUnlock);\r\n    }\r\n\r\n    /**\r\n     * @notice Creates a new endorsed vault with default profit max unlock time.\r\n     * @param _asset Address of the underlying asset.\r\n     * @param _category Category of the vault.\r\n     * @param _depositLimit The deposit limit to start the vault with.\r\n     * @return _vault Address of the newly created vault.\r\n     */\r\n    function newVault(\r\n        address _asset,\r\n        uint256 _category,\r\n        uint256 _depositLimit\r\n    ) external virtual onlyPositionHolder(DADDY) returns (address) {\r\n        return\r\n            _newVault(_asset, _category, _depositLimit, defaultProfitMaxUnlock);\r\n    }\r\n\r\n    /**\r\n     * @notice Creates a new endorsed vault.\r\n     * @param _asset Address of the underlying asset.\r\n     * @param _category Category of the vault.\r\n     * @param _depositLimit The deposit limit to start the vault with.\r\n     * @param _profitMaxUnlockTime Time until profits are fully unlocked.\r\n     * @return _vault Address of the newly created vault.\r\n     */\r\n    function newVault(\r\n        address _asset,\r\n        uint256 _category,\r\n        uint256 _depositLimit,\r\n        uint256 _profitMaxUnlockTime\r\n    ) external virtual onlyPositionHolder(DADDY) returns (address) {\r\n        return\r\n            _newVault(_asset, _category, _depositLimit, _profitMaxUnlockTime);\r\n    }\r\n\r\n    /**\r\n     * @notice Creates a new endorsed vault.\r\n     * @param _asset Address of the underlying asset.\r\n     * @param _category Category of the vault.\r\n     * @param _depositLimit The deposit limit to start the vault with.\r\n     * @param _profitMaxUnlockTime Time until profits are fully unlocked.\r\n     * @return _vault Address of the newly created vault.\r\n     */\r\n    function _newVault(\r\n        address _asset,\r\n        uint256 _category,\r\n        uint256 _depositLimit,\r\n        uint256 _profitMaxUnlockTime\r\n    ) internal virtual returns (address _vault) {\r\n        string memory _categoryString = Strings.toString(_category);\r\n\r\n        // Name is \"{SYMBOL}-{CATEGORY} yVault\"\r\n        string memory _name = string(\r\n            abi.encodePacked(\r\n                ERC20(_asset).symbol(),\r\n                \"-\",\r\n                _categoryString,\r\n                \" yVault\"\r\n            )\r\n        );\r\n        // Symbol is \"yv{SYMBOL}-{CATEGORY}\".\r\n        string memory _symbol = string(\r\n            abi.encodePacked(\"yv\", ERC20(_asset).symbol(), \"-\", _categoryString)\r\n        );\r\n\r\n        // Deploy through the registry so it is automatically endorsed.\r\n        _vault = Registry(getPositionHolder(REGISTRY)).newEndorsedVault(\r\n            _asset,\r\n            _name,\r\n            _symbol,\r\n            address(this),\r\n            _profitMaxUnlockTime\r\n        );\r\n\r\n        // Check that a vault does not exist for that asset, api and category.\r\n        // This reverts late to not waste gas when used correctly.\r\n        string memory _apiVersion = IVault(_vault).apiVersion();\r\n        if (_assetToVault[_asset][_apiVersion][_category] != address(0))\r\n            revert AlreadyDeployed(\r\n                _assetToVault[_asset][_apiVersion][_category]\r\n            );\r\n\r\n        // Deploy a new debt allocator for the vault.\r\n        address _debtAllocator = _deployAllocator(_vault);\r\n\r\n        // Give out roles on the new vault.\r\n        _sanctify(_vault, _debtAllocator);\r\n\r\n        // Set up the accountant.\r\n        _setAccountant(_vault);\r\n\r\n        if (_depositLimit != 0) {\r\n            _setDepositLimit(_vault, _depositLimit);\r\n        }\r\n\r\n        // Add the vault config to the mapping.\r\n        vaultConfig[_vault] = VaultConfig({\r\n            asset: _asset,\r\n            category: _category,\r\n            debtAllocator: _debtAllocator,\r\n            index: vaults.length\r\n        });\r\n\r\n        // Add the vault to the mapping.\r\n        _assetToVault[_asset][_apiVersion][_category] = _vault;\r\n\r\n        // Add the vault to the array.\r\n        vaults.push(_vault);\r\n\r\n        // Emit event for new vault.\r\n        emit AddedNewVault(_vault, _debtAllocator, _category);\r\n    }\r\n\r\n    /**\r\n     * @dev Deploys a debt allocator for the specified vault.\r\n     * @param _vault Address of the vault.\r\n     * @return _debtAllocator Address of the deployed debt allocator.\r\n     */\r\n    function _deployAllocator(\r\n        address _vault\r\n    ) internal virtual returns (address _debtAllocator) {\r\n        address factory = getPositionHolder(ALLOCATOR_FACTORY);\r\n\r\n        // If we have a factory set.\r\n        if (factory != address(0)) {\r\n            // Deploy a new debt allocator for the vault with Brain as the gov.\r\n            _debtAllocator = DebtAllocatorFactory(factory).newDebtAllocator(\r\n                _vault\r\n            );\r\n        } else {\r\n            // If no factory is set we should be using one central allocator.\r\n            _debtAllocator = getPositionHolder(DEBT_ALLOCATOR);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Assigns roles to the newly added vault.\r\n     *\r\n     * This will override any previously set roles for the holders. But not effect\r\n     * the roles held by other addresses.\r\n     *\r\n     * @param _vault Address of the vault to sanctify.\r\n     * @param _debtAllocator Address of the debt allocator for the vault.\r\n     */\r\n    function _sanctify(\r\n        address _vault,\r\n        address _debtAllocator\r\n    ) internal virtual {\r\n        // Set the roles for daddy.\r\n        _setRole(_vault, _positions[DADDY]);\r\n\r\n        // Set the roles for Brain.\r\n        _setRole(_vault, _positions[BRAIN]);\r\n\r\n        // Set the roles for Security.\r\n        _setRole(_vault, _positions[SECURITY]);\r\n\r\n        // Set the roles for the Keeper.\r\n        _setRole(_vault, _positions[KEEPER]);\r\n\r\n        // Set the roles for the Strategy Manager.\r\n        _setRole(_vault, _positions[STRATEGY_MANAGER]);\r\n\r\n        // Give the specific debt allocator its roles.\r\n        _setRole(\r\n            _vault,\r\n            Position(_debtAllocator, _positions[DEBT_ALLOCATOR].roles)\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @dev Used internally to set the roles on a vault for a given position.\r\n     *   Will not set the roles if the position holder is address(0).\r\n     *   This does not check that the roles are !=0 because it is expected that\r\n     *   the holder will be set to 0 if the position is not being used.\r\n     *\r\n     * @param _vault Address of the vault.\r\n     * @param _position Holder address and roles to set.\r\n     */\r\n    function _setRole(\r\n        address _vault,\r\n        Position memory _position\r\n    ) internal virtual {\r\n        if (_position.holder != address(0)) {\r\n            IVault(_vault).set_role(_position.holder, uint256(_position.roles));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Sets the accountant on the vault and adds the vault to the accountant.\r\n     *   This temporarily gives the `ACCOUNTANT_MANAGER` role to this contract.\r\n     * @param _vault Address of the vault to set up the accountant for.\r\n     */\r\n    function _setAccountant(address _vault) internal virtual {\r\n        // Get the current accountant.\r\n        address accountant = getPositionHolder(ACCOUNTANT);\r\n\r\n        // If there is an accountant set.\r\n        if (accountant != address(0)) {\r\n            // Temporarily give this contract the ability to set the accountant.\r\n            IVault(_vault).add_role(address(this), Roles.ACCOUNTANT_MANAGER);\r\n\r\n            // Set the account on the vault.\r\n            IVault(_vault).set_accountant(accountant);\r\n\r\n            // Take away the role.\r\n            IVault(_vault).remove_role(address(this), Roles.ACCOUNTANT_MANAGER);\r\n\r\n            // Whitelist the vault in the accountant.\r\n            Accountant(accountant).addVault(_vault);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Used to set an initial deposit limit when a new vault is deployed.\r\n     *   Any further updates to the limit will need to be done by an address that\r\n     *   holds the `DEPOSIT_LIMIT_MANAGER` role.\r\n     * @param _vault Address of the newly deployed vault.\r\n     * @param _depositLimit The deposit limit to set.\r\n     */\r\n    function _setDepositLimit(\r\n        address _vault,\r\n        uint256 _depositLimit\r\n    ) internal virtual {\r\n        // Temporarily give this contract the ability to set the deposit limit.\r\n        IVault(_vault).add_role(address(this), Roles.DEPOSIT_LIMIT_MANAGER);\r\n\r\n        // Set the initial deposit limit on the vault.\r\n        IVault(_vault).set_deposit_limit(_depositLimit);\r\n\r\n        // Take away the role.\r\n        IVault(_vault).remove_role(address(this), Roles.DEPOSIT_LIMIT_MANAGER);\r\n    }\r\n\r\n    /*//////////////////////////////////////////////////////////////\r\n                            VAULT MANAGEMENT\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    /**\r\n     * @notice Adds a new vault to the RoleManager with the specified category.\r\n     * @dev If not already endorsed this function will endorse the vault.\r\n     *  A new debt allocator will be deployed and configured.\r\n     * @param _vault Address of the vault to be added.\r\n     * @param _category Category associated with the vault.\r\n     */\r\n    function addNewVault(address _vault, uint256 _category) external virtual {\r\n        address _debtAllocator = _deployAllocator(_vault);\r\n        addNewVault(_vault, _category, _debtAllocator);\r\n    }\r\n\r\n    /**\r\n     * @notice Adds a new vault to the RoleManager with the specified category and debt allocator.\r\n     * @dev If not already endorsed this function will endorse the vault.\r\n     * @param _vault Address of the vault to be added.\r\n     * @param _category Category associated with the vault.\r\n     * @param _debtAllocator Address of the debt allocator for the vault.\r\n     */\r\n    function addNewVault(\r\n        address _vault,\r\n        uint256 _category,\r\n        address _debtAllocator\r\n    ) public virtual onlyPositionHolder(DADDY) {\r\n        // Check that a vault does not exist for that asset, api and category.\r\n        address _asset = IVault(_vault).asset();\r\n        string memory _apiVersion = IVault(_vault).apiVersion();\r\n        if (_assetToVault[_asset][_apiVersion][_category] != address(0))\r\n            revert AlreadyDeployed(\r\n                _assetToVault[_asset][_apiVersion][_category]\r\n            );\r\n\r\n        // If not the current role manager.\r\n        if (IVault(_vault).role_manager() != address(this)) {\r\n            // Accept the position of role manager.\r\n            IVault(_vault).accept_role_manager();\r\n        }\r\n\r\n        // Get the current registry.\r\n        address registry = getPositionHolder(REGISTRY);\r\n\r\n        // Check if the vault has been endorsed yet in the registry.\r\n        if (!Registry(registry).isEndorsed(_vault)) {\r\n            // If not endorse it.\r\n            // NOTE: This will revert if adding a vault of an older version.\r\n            Registry(registry).endorseMultiStrategyVault(_vault);\r\n        }\r\n\r\n        // Set the roles up.\r\n        _sanctify(_vault, _debtAllocator);\r\n\r\n        // Only set an accountant if there is not one set yet.\r\n        if (IVault(_vault).accountant() == address(0)) {\r\n            _setAccountant(_vault);\r\n        }\r\n\r\n        // Add the vault config to the mapping.\r\n        vaultConfig[_vault] = VaultConfig({\r\n            asset: _asset,\r\n            category: _category,\r\n            debtAllocator: _debtAllocator,\r\n            index: vaults.length\r\n        });\r\n\r\n        // Add the vault to the mapping.\r\n        _assetToVault[_asset][_apiVersion][_category] = _vault;\r\n\r\n        // Add the vault to the array.\r\n        vaults.push(_vault);\r\n\r\n        // Emit event.\r\n        emit AddedNewVault(_vault, _debtAllocator, _category);\r\n    }\r\n\r\n    /**\r\n     * @notice Update a `_vault`s debt allocator.\r\n     * @dev This will deploy a new allocator using the current\r\n     *   allocator factory set.\r\n     * @param _vault Address of the vault to update the allocator for.\r\n     */\r\n    function updateDebtAllocator(\r\n        address _vault\r\n    ) external virtual returns (address _newDebtAllocator) {\r\n        _newDebtAllocator = _deployAllocator(_vault);\r\n        updateDebtAllocator(_vault, _newDebtAllocator);\r\n    }\r\n\r\n    /**\r\n     * @notice Update a `_vault`s debt allocator to a specified `_debtAllocator`.\r\n     * @param _vault Address of the vault to update the allocator for.\r\n     * @param _debtAllocator Address of the new debt allocator.\r\n     */\r\n    function updateDebtAllocator(\r\n        address _vault,\r\n        address _debtAllocator\r\n    ) public virtual onlyPositionHolder(BRAIN) {\r\n        // Make sure the vault has been added to the role manager.\r\n        require(vaultConfig[_vault].asset != address(0), \"vault not added\");\r\n\r\n        // Remove the roles from the old allocator.\r\n        _setRole(_vault, Position(vaultConfig[_vault].debtAllocator, 0));\r\n\r\n        // Give the new debt allocator the relevant roles.\r\n        _setRole(\r\n            _vault,\r\n            Position(_debtAllocator, _positions[DEBT_ALLOCATOR].roles)\r\n        );\r\n\r\n        // Update the vaults config.\r\n        vaultConfig[_vault].debtAllocator = _debtAllocator;\r\n\r\n        // Emit event.\r\n        emit UpdateDebtAllocator(_vault, _debtAllocator);\r\n    }\r\n\r\n    /**\r\n     * @notice Update a `_vault`s keeper to a specified `_keeper`.\r\n     * @param _vault Address of the vault to update the keeper for.\r\n     * @param _keeper Address of the new keeper.\r\n     */\r\n    function updateKeeper(\r\n        address _vault,\r\n        address _keeper\r\n    ) external virtual onlyPositionHolder(BRAIN) {\r\n        // Make sure the vault has been added to the role manager.\r\n        require(vaultConfig[_vault].asset != address(0), \"vault not added\");\r\n\r\n        // Remove the roles from the old keeper if active.\r\n        address defaultKeeper = getPositionHolder(KEEPER);\r\n        if (\r\n            _keeper != defaultKeeper && IVault(_vault).roles(defaultKeeper) != 0\r\n        ) {\r\n            _setRole(_vault, Position(defaultKeeper, 0));\r\n        }\r\n\r\n        // Give the new keeper the relevant roles.\r\n        _setRole(_vault, Position(_keeper, _positions[KEEPER].roles));\r\n    }\r\n\r\n    /**\r\n     * @notice Removes a vault from the RoleManager.\r\n     * @dev This will NOT un-endorse the vault from the registry.\r\n     * @param _vault Address of the vault to be removed.\r\n     */\r\n    function removeVault(\r\n        address _vault\r\n    ) external virtual onlyPositionHolder(BRAIN) {\r\n        // Get the vault specific config.\r\n        VaultConfig memory config = vaultConfig[_vault];\r\n        // Make sure the vault has been added to the role manager.\r\n        require(config.asset != address(0), \"vault not added\");\r\n\r\n        // Transfer the role manager position.\r\n        IVault(_vault).transfer_role_manager(chad);\r\n\r\n        // Address of the vault to replace it with.\r\n        address vaultToMove = vaults[vaults.length - 1];\r\n\r\n        // Move the last vault to the index of `_vault`\r\n        vaults[config.index] = vaultToMove;\r\n        vaultConfig[vaultToMove].index = config.index;\r\n\r\n        // Remove the last item.\r\n        vaults.pop();\r\n\r\n        // Delete the vault from the mapping.\r\n        delete _assetToVault[config.asset][IVault(_vault).apiVersion()][\r\n            config.category\r\n        ];\r\n\r\n        // Delete the config for `_vault`.\r\n        delete vaultConfig[_vault];\r\n\r\n        emit RemovedVault(_vault);\r\n    }\r\n\r\n    /**\r\n     * @notice Removes a specific role(s) for a `_holder` from the `_vaults`.\r\n     * @dev Can be used to remove one specific role or multiple.\r\n     * @param _vaults Array of vaults to adjust.\r\n     * @param _holder Address who's having a role removed.\r\n     * @param _role The role or roles to remove from the `_holder`.\r\n     */\r\n    function removeRoles(\r\n        address[] calldata _vaults,\r\n        address _holder,\r\n        uint256 _role\r\n    ) external virtual onlyGovernance {\r\n        address _vault;\r\n        for (uint256 i = 0; i < _vaults.length; ++i) {\r\n            _vault = _vaults[i];\r\n            // Make sure the vault is added to this Role Manager.\r\n            require(vaultConfig[_vault].asset != address(0), \"vault not added\");\r\n\r\n            // Remove the role.\r\n            IVault(_vault).remove_role(_holder, _role);\r\n        }\r\n    }\r\n\r\n    /*//////////////////////////////////////////////////////////////\r\n                            SETTERS\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    /**\r\n     * @notice Setter function for updating a positions roles.\r\n     * @param _position Identifier for the position.\r\n     * @param _newRoles New roles for the position.\r\n     */\r\n    function setPositionRoles(\r\n        bytes32 _position,\r\n        uint256 _newRoles\r\n    ) external virtual onlyGovernance {\r\n        // Cannot change the debt allocator or keeper roles since holder can be updated.\r\n        require(\r\n            _position != DEBT_ALLOCATOR && _position != KEEPER,\r\n            \"cannot update\"\r\n        );\r\n        _positions[_position].roles = uint96(_newRoles);\r\n\r\n        emit UpdatePositionRoles(_position, _newRoles);\r\n    }\r\n\r\n    /**\r\n     * @notice Setter function for updating a positions holder.\r\n     * @param _position Identifier for the position.\r\n     * @param _newHolder New address for position.\r\n     */\r\n    function setPositionHolder(\r\n        bytes32 _position,\r\n        address _newHolder\r\n    ) external virtual onlyGovernance {\r\n        _positions[_position].holder = _newHolder;\r\n\r\n        emit UpdatePositionHolder(_position, _newHolder);\r\n    }\r\n\r\n    /**\r\n     * @notice Sets the default time until profits are fully unlocked for new vaults.\r\n     * @param _newDefaultProfitMaxUnlock New value for defaultProfitMaxUnlock.\r\n     */\r\n    function setDefaultProfitMaxUnlock(\r\n        uint256 _newDefaultProfitMaxUnlock\r\n    ) external virtual onlyGovernance {\r\n        defaultProfitMaxUnlock = _newDefaultProfitMaxUnlock;\r\n\r\n        emit UpdateDefaultProfitMaxUnlock(_newDefaultProfitMaxUnlock);\r\n    }\r\n\r\n    /*//////////////////////////////////////////////////////////////\r\n                            VIEW METHODS\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    /**\r\n     * @notice Get the name of this contract.\r\n     */\r\n    function name() external view virtual returns (string memory) {\r\n        return string(abi.encodePacked(_name_));\r\n    }\r\n\r\n    /**\r\n     * @notice Get all vaults that this role manager controls..\r\n     * @return The full array of vault addresses.\r\n     */\r\n    function getAllVaults() external view virtual returns (address[] memory) {\r\n        return vaults;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vault for a specific asset, api and category.\r\n     * @dev This will return address(0) if one has not been added or deployed.\r\n     *\r\n     * @param _asset The underlying asset used.\r\n     * @param _apiVersion The version of the vault.\r\n     * @param _category The category of the vault.\r\n     * @return The vault for the specified `_asset`, `_apiVersion` and `_category`.\r\n     */\r\n    function getVault(\r\n        address _asset,\r\n        string memory _apiVersion,\r\n        uint256 _category\r\n    ) external view virtual returns (address) {\r\n        return _assetToVault[_asset][_apiVersion][_category];\r\n    }\r\n\r\n    /**\r\n     * @notice Check if a vault is managed by this contract.\r\n     * @dev This will check if the `asset` variable in the struct has been\r\n     *   set for an easy external view check.\r\n     *\r\n     *   Does not check the vaults `role_manager` position since that can be set\r\n     *   by anyone for a random vault.\r\n     *\r\n     * @param _vault Address of the vault to check.\r\n     * @return . The vaults role manager status.\r\n     */\r\n    function isVaultsRoleManager(\r\n        address _vault\r\n    ) external view virtual returns (bool) {\r\n        return vaultConfig[_vault].asset != address(0);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the debt allocator for a specific vault.\r\n     * @dev Will return address(0) if the vault is not managed by this contract.\r\n     * @param _vault Address of the vault.\r\n     * @return . Address of the debt allocator if any.\r\n     */\r\n    function getDebtAllocator(\r\n        address _vault\r\n    ) external view virtual returns (address) {\r\n        return vaultConfig[_vault].debtAllocator;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the category for a specific vault.\r\n     * @dev Will return 0 if the vault is not managed by this contract.\r\n     * @param _vault Address of the vault.\r\n     * @return . The category of the vault if any.\r\n     */\r\n    function getCategory(\r\n        address _vault\r\n    ) external view virtual returns (uint256) {\r\n        return vaultConfig[_vault].category;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address and roles given to a specific position.\r\n     * @param _positionId The position identifier.\r\n     * @return The address that holds that position.\r\n     * @return The roles given to the specified position.\r\n     */\r\n    function getPosition(\r\n        bytes32 _positionId\r\n    ) public view virtual returns (address, uint256) {\r\n        Position memory _position = _positions[_positionId];\r\n        return (_position.holder, uint256(_position.roles));\r\n    }\r\n\r\n    /**\r\n     * @notice Get the current address assigned to a specific position.\r\n     * @param _positionId The position identifier.\r\n     * @return The current address assigned to the specified position.\r\n     */\r\n    function getPositionHolder(\r\n        bytes32 _positionId\r\n    ) public view virtual returns (address) {\r\n        return _positions[_positionId].holder;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the current roles given to a specific position ID.\r\n     * @param _positionId The position identifier.\r\n     * @return The current roles given to the specified position ID.\r\n     */\r\n    function getPositionRoles(\r\n        bytes32 _positionId\r\n    ) public view virtual returns (uint256) {\r\n        return uint256(_positions[_positionId].roles);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the Daddy position.\r\n     * @return The address assigned to the Daddy position.\r\n     */\r\n    function getDaddy() external view virtual returns (address) {\r\n        return getPositionHolder(DADDY);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the Brain position.\r\n     * @return The address assigned to the Brain position.\r\n     */\r\n    function getBrain() external view virtual returns (address) {\r\n        return getPositionHolder(BRAIN);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the Security position.\r\n     * @return The address assigned to the Security position.\r\n     */\r\n    function getSecurity() external view virtual returns (address) {\r\n        return getPositionHolder(SECURITY);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the Keeper position.\r\n     * @return The address assigned to the Keeper position.\r\n     */\r\n    function getKeeper() external view virtual returns (address) {\r\n        return getPositionHolder(KEEPER);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the strategy manager.\r\n     * @return The address assigned to the strategy manager.\r\n     */\r\n    function getStrategyManager() external view virtual returns (address) {\r\n        return getPositionHolder(STRATEGY_MANAGER);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the accountant.\r\n     * @return The address assigned to the accountant.\r\n     */\r\n    function getAccountant() external view virtual returns (address) {\r\n        return getPositionHolder(ACCOUNTANT);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the Registry.\r\n     * @return The address assigned to the Registry.\r\n     */\r\n    function getRegistry() external view virtual returns (address) {\r\n        return getPositionHolder(REGISTRY);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to be the debt allocator if any.\r\n     * @return The address assigned to be the debt allocator if any.\r\n     */\r\n    function getDebtAllocator() external view virtual returns (address) {\r\n        return getPositionHolder(DEBT_ALLOCATOR);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the address assigned to the allocator factory.\r\n     * @return The address assigned to the allocator factory.\r\n     */\r\n    function getAllocatorFactory() external view virtual returns (address) {\r\n        return getPositionHolder(ALLOCATOR_FACTORY);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the roles given to the Daddy position.\r\n     * @return The roles given to the Daddy position.\r\n     */\r\n    function getDaddyRoles() external view virtual returns (uint256) {\r\n        return getPositionRoles(DADDY);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the roles given to the Brain position.\r\n     * @return The roles given to the Brain position.\r\n     */\r\n    function getBrainRoles() external view virtual returns (uint256) {\r\n        return getPositionRoles(BRAIN);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the roles given to the Security position.\r\n     * @return The roles given to the Security position.\r\n     */\r\n    function getSecurityRoles() external view virtual returns (uint256) {\r\n        return getPositionRoles(SECURITY);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the roles given to the Keeper position.\r\n     * @return The roles given to the Keeper position.\r\n     */\r\n    function getKeeperRoles() external view virtual returns (uint256) {\r\n        return getPositionRoles(KEEPER);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the roles given to the debt allocators.\r\n     * @return The roles given to the debt allocators.\r\n     */\r\n    function getDebtAllocatorRoles() external view virtual returns (uint256) {\r\n        return getPositionRoles(DEBT_ALLOCATOR);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the roles given to the strategy manager.\r\n     * @return The roles given to the strategy manager.\r\n     */\r\n    function getStrategyManagerRoles() external view virtual returns (uint256) {\r\n        return getPositionRoles(STRATEGY_MANAGER);\r\n    }\r\n}","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106103425760003560e01c80638440d167116101b8578063ceb68c2311610104578063e0a4edf3116100a2578063ef8d03da1161007c578063ef8d03da14610765578063f39c38a01461078c578063f857ef671461079f578063fc036d7c1461081757600080fd5b8063e0a4edf314610737578063e33c71d01461074a578063e7c512771461075257600080fd5b8063d811ae21116100de578063d811ae21146106f2578063de490aca146106fa578063de8c1b791461070f578063deb20d871461072457600080fd5b8063ceb68c23146106c4578063d013355a146106d7578063d38bfff4146106df57600080fd5b80639fc2c47611610171578063b458dd011161014b578063b458dd0114610678578063b4936a591461068b578063bfb7d4a31461069e578063caa61cb0146106b157600080fd5b80639fc2c47614610648578063a1b770461461065d578063a7bebf9f1461066557600080fd5b80638440d167146105a3578063862a179e146105cf5780638808f66d146105e45780638b9d2940146105f95780638c64ea4a1461062057806397331bf91461063357600080fd5b8063391b6f4e1161029257806362dd471611610230578063732742761161020a578063732742761461058357806374e417d71461058b57806375e48e7e146105935780637de9cd221461059b57600080fd5b806362dd471614610539578063647246041461054c5780636b802bc61461057b57600080fd5b80635594851d1161026c5780635594851d146104d85780635aa6e675146104e05780635ab1bd53146104f35780635dcd6745146104fb57600080fd5b8063391b6f4e146104bf57806348dff373146104c75780634c12c773146104d057600080fd5b80631507a04d116102ff5780632541897f116102d95780632541897f1461047e5780632eeabd8f146104865780633080cef11461049957806338906554146104ac57600080fd5b80631507a04d146103f35780631928b3cb14610406578063238efcbc1461047657600080fd5b806306433b1b1461034757806306fdde031461036f57806309e5d1b7146103845780630a1c187c146103ab57806314adb2f3146103d657806314f675d2146103de575b600080fd5b61035c600080516020612e6d83398151915281565b6040519081526020015b60405180910390f35b61037761082c565b6040516103669190612824565b61035c7f250bebb02a4f564f8ff4a1d2af194d82b25fee33eab79ab5d8256144e0ed0dfe81565b6103be6103b936600461283e565b610899565b6040516001600160a01b039091168152602001610366565b61035c6108b4565b6103f16103ec36600461286c565b6108d2565b005b6103f16104013660046128a5565b610a33565b61045761041436600461283e565b6000908152600460209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160601b03169290910182905291565b604080516001600160a01b039093168352602083019190915201610366565b6103f1610b23565b6103be610bcb565b6103be610494366004612931565b610be4565b6103f16104a736600461295d565b610c15565b6103f16104ba36600461286c565b611144565b6103be6112e4565b61035c60035481565b61035c6112fd565b61035c611316565b6000546103be906001600160a01b031681565b6103be61132f565b61052961050936600461299f565b6001600160a01b0390811660009081526005602052604090205416151590565b6040519015158152602001610366565b6103be6105473660046129bc565b611348565b6103be61055a36600461299f565b6001600160a01b039081166000908152600560205260409020600201541690565b61035c611378565b61035c611391565b6103be6113aa565b6103be6113c3565b6103be6113ee565b61035c6105b136600461299f565b6001600160a01b031660009081526005602052604090206001015490565b61035c600080516020612ecd83398151915281565b61035c600080516020612e8d83398151915281565b61035c7f1629cfbd564ce33f37c84741f82a28dcd353c97db5819722102f8704671969be81565b6103be61062e36600461283e565b611419565b61063b611443565b60405161036691906129f7565b61035c600080516020612e4d83398151915281565b6103be6114a5565b6103f161067336600461283e565b6114be565b6103be610686366004612a44565b611501565b6103f1610699366004612a79565b611532565b6103be6106ac36600461299f565b611593565b6103f16106bf366004612a9e565b6115af565b6103f16106d236600461299f565b611685565b61035c611972565b6103f16106ed36600461299f565b61198b565b6103be611a22565b61035c600080516020612eed83398151915281565b61035c600080516020612f0d83398151915281565b6103f1610732366004612931565b611a3b565b61035c61074536600461283e565b611a58565b6103be611a7a565b6103be610760366004612b2f565b611a93565b6103be7f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5281565b6001546103be906001600160a01b031681565b6107e26107ad36600461299f565b60056020526000908152604090208054600182015460028301546003909301546001600160a01b039283169391929091169084565b60405161036694939291906001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b61035c600080516020612ead83398151915281565b6040517f596561726e205633205661756c7420526f6c65204d616e6167657200000000006020820152606090603b0160405160208183030381529060405261087390612bcb565b60405160200161088591815260200190565b604051602081830303815290604052905090565b6000908152600460205260409020546001600160a01b031690565b60006108cd600080516020612ecd833981519152611a58565b905090565b600080516020612f0d8339815191526108ea81611ae6565b6001600160a01b038381166000908152600560205260409020541661092a5760405162461bcd60e51b815260040161092190612bef565b60405180910390fd5b6040805180820182526001600160a01b0380861660009081526005602090815293812060020154909116825291810191909152610968908490611b52565b604080518082019091526001600160a01b0383168152600080516020612e8d833981519152600052600460209081527fb33d6e6dff8e4e4e4050e51a87d0b1f91bda65467f96287ee8d6049a2e99a85154600160a01b90046001600160601b0316908201526109d8908490611b52565b6001600160a01b0383811660008181526005602052604080822060020180546001600160a01b0319169487169485179055517f46b03560e5440592db04cf536396abd2d0e1da05cd4bab259a01af406a8686ed9190a3505050565b610a3b611bd6565b6000805b84811015610b1b57858582818110610a5957610a59612c18565b9050602002016020810190610a6e919061299f565b6001600160a01b0380821660009081526005602052604090205491935016610aa85760405162461bcd60e51b815260040161092190612bef565b60405163e2bf56dd60e01b81526001600160a01b0385811660048301526024820185905283169063e2bf56dd90604401600060405180830381600087803b158015610af257600080fd5b505af1158015610b06573d6000803e3d6000fd5b5050505080610b1490612c44565b9050610a3f565b505050505050565b6001546001600160a01b03163314610b735760405162461bcd60e51b81526020600482015260136024820152722170656e64696e6720676f7665726e616e636560681b6044820152606401610921565b6000805460405133926001600160a01b03909216917f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce8091a3600080546001600160a01b03199081163317909155600180549091169055565b60006108cd600080516020612ead833981519152610899565b6000600080516020612eed833981519152610bfe81611ae6565b610c0d84846000600354611c20565b949350505050565b600080516020612eed833981519152610c2d81611ae6565b6000846001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c919190612c5d565b90506000856001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cd3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cfb9190810190612c7a565b6001600160a01b03831660009081526006602052604080822090519293509091610d26908490612ce8565b9081526040805160209281900383019020600089815292529020546001600160a01b031614610db1576001600160a01b038216600090815260066020526040908190209051610d76908390612ce8565b9081526040805160209281900383018120600089815293529120546329ab51bf60e01b82526001600160a01b03166004820152602401610921565b306001600160a01b0316866001600160a01b03166379b989176040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1d9190612c5d565b6001600160a01b031614610e7f57856001600160a01b031663f776bf1f6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b505050505b6000610e98600080516020612e6d833981519152610899565b60405163a237e94d60e01b81526001600160a01b0389811660048301529192509082169063a237e94d90602401602060405180830381865afa158015610ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f069190612d04565b610f6657604051630ab322d960e01b81526001600160a01b038881166004830152821690630ab322d990602401600060405180830381600087803b158015610f4d57600080fd5b505af1158015610f61573d6000803e3d6000fd5b505050505b610f708786612075565b60006001600160a01b0316876001600160a01b0316634fb3ccc56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdd9190612c5d565b6001600160a01b031603610ff457610ff487612324565b604080516080810182526001600160a01b0380861680835260208084018b81528a841685870190815260028054606088019081528f8716600090815260058652898120985189549089166001600160a01b0319918216178a55945160018a0155925191880180549290971691909316179094555160039094019390935581526006909152819020905188919061108b908590612ce8565b90815260408051918290036020908101832060008b8152915290812080546001600160a01b039485166001600160a01b0319918216179091556002805460018101825592527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180548b851692168217905591871691907f65fe7f527479e9a13137b5a7af43efff08bb8e165ff5897ad493bb0362a690c190611133908a815260200190565b60405180910390a350505050505050565b600080516020612f0d83398151915261115c81611ae6565b6001600160a01b03838116600090815260056020526040902054166111935760405162461bcd60e51b815260040161092190612bef565b60006111ac600080516020612ecd833981519152610899565b9050806001600160a01b0316836001600160a01b0316141580156112385750604051634c9ba32160e11b81526001600160a01b038281166004830152851690639937464290602401602060405180830381865afa158015611211573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112359190612d26565b15155b1561126e5761126e846040518060400160405280846001600160a01b0316815260200160006001600160601b0316815250611b52565b604080518082019091526001600160a01b0384168152600080516020612ecd833981519152600052600460209081527fc0f9a12d667a5c774acef575ed1617cc006b6e66e225868264b4c1aa563dae6b54600160a01b90046001600160601b0316908201526112de908590611b52565b50505050565b60006108cd600080516020612ecd833981519152610899565b60006108cd600080516020612ead833981519152611a58565b60006108cd600080516020612e4d833981519152611a58565b60006108cd600080516020612e6d833981519152610899565b6000600080516020612eed83398151915261136281611ae6565b61136e86868686611c20565b9695505050505050565b60006108cd600080516020612f0d833981519152611a58565b60006108cd600080516020612eed833981519152611a58565b60006108cd600080516020612e4d833981519152610899565b60006108cd7f250bebb02a4f564f8ff4a1d2af194d82b25fee33eab79ab5d8256144e0ed0dfe610899565b60006108cd7f1629cfbd564ce33f37c84741f82a28dcd353c97db5819722102f8704671969be610899565b6002818154811061142957600080fd5b6000918252602090912001546001600160a01b0316905081565b6060600280548060200260200160405190810160405280929190818152602001828054801561149b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161147d575b5050505050905090565b60006108cd600080516020612e8d833981519152610899565b6114c6611bd6565b60038190556040518181527f4c5e7edcabd189a3cdd68d6b4890f6b8159bf382e2d11a87aa39851f0377432f9060200160405180910390a150565b6000600080516020612eed83398151915261151b81611ae6565b611529858585600354611c20565b95945050505050565b61153a611bd6565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0385169081179091559051909184917f8c42303edb98aad4f3e4f1a15363dda2db344e9fd66ecff9acf62f770c474fa39190a35050565b600061159e826124a9565b90506115aa82826108d2565b919050565b6115b7611bd6565b600080516020612e8d83398151915282141580156115e35750600080516020612ecd8339815191528214155b61161f5760405162461bcd60e51b815260206004820152600d60248201526c63616e6e6f742075706461746560981b6044820152606401610921565b60008281526004602090815260409182902080546001600160a01b0316600160a01b6001600160601b03861602179055905182815283917ff8a7e043f1e7310711bc663ed81ae8855aa474348c57a6461b9f52a4fa88a94d910160405180910390a25050565b600080516020612f0d83398151915261169d81611ae6565b6001600160a01b03808316600090815260056020908152604091829020825160808101845281548516808252600183015493820193909352600282015490941692840192909252600390910154606083015261170b5760405162461bcd60e51b815260040161092190612bef565b60405163ef54cefd60e01b81526001600160a01b037f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff528116600483015284169063ef54cefd90602401600060405180830381600087803b15801561176e57600080fd5b505af1158015611782573d6000803e3d6000fd5b5050505060006002600160028054905061179c9190612d3f565b815481106117ac576117ac612c18565b9060005260206000200160009054906101000a90046001600160a01b031690508060028360600151815481106117e4576117e4612c18565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905560608501519284168252600590526040902060030155600280548061183357611833612d52565b60008281526020808220830160001990810180546001600160a01b031916905590920190925583516001600160a01b039081168352600690915260408083208151630258294160e41b81529151909392881692632582941092600480820193918290030181865afa1580156118ac573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118d49190810190612c7a565b6040516118e19190612ce8565b908152604080516020928190038301812085840151600090815290845282812080546001600160a01b03199081169091556001600160a01b03891680835260059095529281208054841681556001810182905560028101805490941690935560039092018290557fa40a7d97cd4243d8bcd193dc4d709afc3717750c5996d9e7216d1a5e0288c4949190a250505050565b60006108cd600080516020612e8d833981519152611a58565b611993611bd6565b6001600160a01b0381166119d85760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b6044820152606401610921565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fa443b483867b0f9db5b03913474dd21935ac5ba70fa6c94e3423ba9be157c44b90600090a250565b60006108cd600080516020612f0d833981519152610899565b6000611a46836124a9565b9050611a53838383610c15565b505050565b600090815260046020526040902054600160a01b90046001600160601b031690565b60006108cd600080516020612eed833981519152610899565b6001600160a01b0383166000908152600660205260408082209051611ab9908590612ce8565b90815260408051602092819003830190206000948552909152909120546001600160a01b03169392505050565b6000546001600160a01b0316331480611b185750611b0381610899565b6001600160a01b0316336001600160a01b0316145b611b4f5760405162461bcd60e51b815260206004820152600860248201526708585b1b1bddd95960c21b6044820152606401610921565b50565b80516001600160a01b031615611bd25780516020820151604051632cf7fd8560e01b81526001600160a01b0392831660048201526001600160601b03909116602482015290831690632cf7fd85906044015b600060405180830381600087803b158015611bbe57600080fd5b505af1158015610b1b573d6000803e3d6000fd5b5050565b6000546001600160a01b03163314611c1e5760405162461bcd60e51b815260206004820152600b60248201526a21676f7665726e616e636560a81b6044820152606401610921565b565b600080611c2c85612579565b90506000866001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611c6e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c969190810190612c7a565b82604051602001611ca8929190612d68565b60405160208183030381529060405290506000876001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611cf9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d219190810190612c7a565b83604051602001611d33929190612db8565b6040516020818303038152906040529050611d5b600080516020612e6d833981519152610899565b6001600160a01b03166317bdd312898484308a6040518663ffffffff1660e01b8152600401611d8e959493929190612e02565b6020604051808303816000875af1158015611dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd19190612c5d565b93506000846001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015611e13573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e3b9190810190612c7a565b6001600160a01b038a1660009081526006602052604080822090519293509091611e66908490612ce8565b908152604080516020928190038301902060008c815292529020546001600160a01b031614611ef1576001600160a01b038916600090815260066020526040908190209051611eb6908390612ce8565b908152604080516020928190038301812060008c815293529120546329ab51bf60e01b82526001600160a01b03166004820152602401610921565b6000611efc866124a9565b9050611f088682612075565b611f1186612324565b8715611f2157611f21868961260c565b604080516080810182526001600160a01b03808d1680835260208084018e815286841685870190815260028054606088019081528e8716600090815260058652898120985189549089166001600160a01b0319918216178a55945160018a01559251918801805492909716919093161790945551600390940193909355815260069091528190209051879190611fb8908590612ce8565b90815260408051918290036020908101832060008e8152915290812080546001600160a01b039485166001600160a01b0319918216179091556002805460018101825592527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180548a851692168217905591831691907f65fe7f527479e9a13137b5a7af43efff08bb8e165ff5897ad493bb0362a690c190612060908d815260200190565b60405180910390a35050505050949350505050565b600080516020612eed83398151915260005260046020908152604080518082019091527fd47b3c79bd50e59096d8ce65b63ebf51be417f69055d0030a5934fa136f10d24546001600160a01b0381168252600160a01b90046001600160601b0316918101919091526120e8908390611b52565b600080516020612f0d83398151915260005260046020908152604080518082019091527f8d0e7cff81b8eff0d9b894fecb0fea5bbeb095356aa51bcebdf3c71720e5bb28546001600160a01b0381168252600160a01b90046001600160601b03169181019190915261215b908390611b52565b600080516020612ead83398151915260005260046020908152604080518082019091527f0f0b81d657455a35b8381ada6898e7d534146b34b30517e64f1480e4d241f39d546001600160a01b0381168252600160a01b90046001600160601b0316918101919091526121ce908390611b52565b600080516020612ecd83398151915260005260046020908152604080518082019091527fc0f9a12d667a5c774acef575ed1617cc006b6e66e225868264b4c1aa563dae6b546001600160a01b0381168252600160a01b90046001600160601b031691810191909152612241908390611b52565b600080516020612e4d83398151915260005260046020908152604080518082019091527f26a8d9344e226b269b0d236a40fe5b87efe6af1e7a3c9ff71fb1cccdf3b9399e546001600160a01b0381168252600160a01b90046001600160601b0316918101919091526122b4908390611b52565b604080518082019091526001600160a01b0382168152600080516020612e8d833981519152600052600460209081527fb33d6e6dff8e4e4e4050e51a87d0b1f91bda65467f96287ee8d6049a2e99a85154600160a01b90046001600160601b031690820152611bd2908390611b52565b600061234f7f1629cfbd564ce33f37c84741f82a28dcd353c97db5819722102f8704671969be610899565b90506001600160a01b03811615611bd2576040516354be77d160e11b8152306004820152600860248201526001600160a01b0383169063a97cefa290604401600060405180830381600087803b1580156123a857600080fd5b505af11580156123bc573d6000803e3d6000fd5b50506040516371da8a8d60e01b81526001600160a01b038481166004830152851692506371da8a8d9150602401600060405180830381600087803b15801561240357600080fd5b505af1158015612417573d6000803e3d6000fd5b505060405163e2bf56dd60e01b8152306004820152600860248201526001600160a01b038516925063e2bf56dd9150604401600060405180830381600087803b15801561246357600080fd5b505af1158015612477573d6000803e3d6000fd5b50506040516312b5ad0160e11b81526001600160a01b0385811660048301528416925063256b5a029150602401611ba4565b6000806124d57f250bebb02a4f564f8ff4a1d2af194d82b25fee33eab79ab5d8256144e0ed0dfe610899565b90506001600160a01b038116156125595760405163028d34c960e41b81526001600160a01b0384811660048301528216906328d34c90906024016020604051808303816000875af115801561252e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125529190612c5d565b9150612573565b612570600080516020612e8d833981519152610899565b91505b50919050565b60606000612586836126fb565b600101905060008167ffffffffffffffff8111156125a6576125a6612ac0565b6040519080825280601f01601f1916602001820160405280156125d0576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846125da57509392505050565b6040516354be77d160e11b815230600482015261010060248201526001600160a01b0383169063a97cefa290604401600060405180830381600087803b15801561265557600080fd5b505af1158015612669573d6000803e3d6000fd5b50506040516337f00e8f60e11b8152600481018490526001600160a01b0385169250636fe01d1e9150602401600060405180830381600087803b1580156126af57600080fd5b505af11580156126c3573d6000803e3d6000fd5b505060405163e2bf56dd60e01b815230600482015261010060248201526001600160a01b038516925063e2bf56dd9150604401611ba4565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061273a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612766576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061278457662386f26fc10000830492506010015b6305f5e100831061279c576305f5e100830492506008015b61271083106127b057612710830492506004015b606483106127c2576064830492506002015b600a83106127ce576001015b92915050565b60005b838110156127ef5781810151838201526020016127d7565b50506000910152565b600081518084526128108160208601602086016127d4565b601f01601f19169290920160200192915050565b60208152600061283760208301846127f8565b9392505050565b60006020828403121561285057600080fd5b5035919050565b6001600160a01b0381168114611b4f57600080fd5b6000806040838503121561287f57600080fd5b823561288a81612857565b9150602083013561289a81612857565b809150509250929050565b600080600080606085870312156128bb57600080fd5b843567ffffffffffffffff808211156128d357600080fd5b818701915087601f8301126128e757600080fd5b8135818111156128f657600080fd5b8860208260051b850101111561290b57600080fd5b6020928301965094505085013561292181612857565b9396929550929360400135925050565b6000806040838503121561294457600080fd5b823561294f81612857565b946020939093013593505050565b60008060006060848603121561297257600080fd5b833561297d81612857565b925060208401359150604084013561299481612857565b809150509250925092565b6000602082840312156129b157600080fd5b813561283781612857565b600080600080608085870312156129d257600080fd5b84356129dd81612857565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b81811015612a385783516001600160a01b031683529284019291840191600101612a13565b50909695505050505050565b600080600060608486031215612a5957600080fd5b8335612a6481612857565b95602085013595506040909401359392505050565b60008060408385031215612a8c57600080fd5b82359150602083013561289a81612857565b60008060408385031215612ab157600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612aff57612aff612ac0565b604052919050565b600067ffffffffffffffff821115612b2157612b21612ac0565b50601f01601f191660200190565b600080600060608486031215612b4457600080fd5b8335612b4f81612857565b9250602084013567ffffffffffffffff811115612b6b57600080fd5b8401601f81018613612b7c57600080fd5b8035612b8f612b8a82612b07565b612ad6565b818152876020838501011115612ba457600080fd5b81602084016020830137600060208383010152809450505050604084013590509250925092565b805160208083015191908110156125735760001960209190910360031b1b16919050565b6020808252600f908201526e1d985d5b1d081b9bdd081859191959608a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612c5657612c56612c2e565b5060010190565b600060208284031215612c6f57600080fd5b815161283781612857565b600060208284031215612c8c57600080fd5b815167ffffffffffffffff811115612ca357600080fd5b8201601f81018413612cb457600080fd5b8051612cc2612b8a82612b07565b818152856020838501011115612cd757600080fd5b6115298260208301602086016127d4565b60008251612cfa8184602087016127d4565b9190910192915050565b600060208284031215612d1657600080fd5b8151801515811461283757600080fd5b600060208284031215612d3857600080fd5b5051919050565b818103818111156127ce576127ce612c2e565b634e487b7160e01b600052603160045260246000fd5b60008351612d7a8184602088016127d4565b602d60f81b9083019081528351612d988160018401602088016127d4565b66081e55985d5b1d60ca1b60019290910191820152600801949350505050565b613cbb60f11b815260008351612dd58160028501602088016127d4565b602d60f81b6002918401918201528351612df68160038401602088016127d4565b01600301949350505050565b600060018060a01b03808816835260a06020840152612e2460a08401886127f8565b8381036040850152612e3681886127f8565b959091166060840152505060800152939250505056fe672945667f64ce7b1755853bd0c8de4d92f2ded2bdeebd30a972846a04a468068c53ae70b0aa86068023c633abcdda89c433a8a76949ea111f756c171fa23663e36275342c99ede79a003741503250226904c6a298f8766fdff5fe056b171b70c764ac13dc7e58eb6edf8aad73d30d911cca42d6ee992ed1eec1b0c56476dc024f78afe9dfc9a0cb0441c27b9405070cd2a48b490636a7bdd09f355e33a5d7deeef8b74e4ca2e456a61430d3d94f2b0a4710302ac13b192e2eec36b17440cfc54c1bd391859805757d865ed7b509d4d26733b7a2204f0afcf45fe0d3efa000a5a26469706673582212204f62da56a9b8cd75182336b57a2a001fdacade7867d92e13340daa5b2614253664736f6c63430008120033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/partial_match/1/0xb3bd6B2E61753C311EFbCF0111f75D29706D9a41/","decoded_constructor_args":[["0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52",{"internalType":"address","name":"_governance","type":"address"}],["0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52",{"internalType":"address","name":"_daddy","type":"address"}],["0x16388463d60FFE0661Cf7F1f31a7D658aC790ff7",{"internalType":"address","name":"_brain","type":"address"}],["0x0000000000000000000000000000000000000000",{"internalType":"address","name":"_security","type":"address"}],["0xc2d26d13582324f10c7c3753B8F5Fc71011EcF57",{"internalType":"address","name":"_keeper","type":"address"}],["0x0000000000000000000000000000000000000000",{"internalType":"address","name":"_strategyManager","type":"address"}],["0xff31A1B020c868F6eA3f61Eb953344920EeCA3af",{"internalType":"address","name":"_registry","type":"address"}]],"compiler_version":"0.8.18+commit.87f61d96","is_verified_via_verifier_alliance":null,"verified_at":"2024-03-29T20:46:25.821367Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60a0604052620d2f006003553480156200001857600080fd5b50604051620033d2380380620033d28339810160408190526200003b91620003b8565b600080546001600160a01b0319166001600160a01b038916908117825560405189928392917f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80908290a350506001600160a01b038616620000d15760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b604482015260640160405180910390fd5b6001600160a01b039586166080818152604080518082018252928352613fff60208085019182527feef8b74e4ca2e456a61430d3d94f2b0a4710302ac13b192e2eec36b17440cfc560009081526004808352955192516001600160601b03908116600160a01b908102948e16949094177fd47b3c79bd50e59096d8ce65b63ebf51be417f69055d0030a5934fa136f10d2455845180860186529b8d168c526111708c84019081527f4c1bd391859805757d865ed7b509d4d26733b7a2204f0afcf45fe0d3efa000a583528784529b519b51811684029b8d169b909b177f8d0e7cff81b8eff0d9b894fecb0fea5bbeb095356aa51bcebdf3c71720e5bb285583518085018552998c168a528982019485527fc764ac13dc7e58eb6edf8aad73d30d911cca42d6ee992ed1eec1b0c56476dc028152858252985193518a168202938b16939093177f0f0b81d657455a35b8381ada6898e7d534146b34b30517e64f1480e4d241f39d5581518083018352968a1687528683018381527f4f78afe9dfc9a0cb0441c27b9405070cd2a48b490636a7bdd09f355e33a5d7de89528484529651965189168102968a16969096177fc0f9a12d667a5c774acef575ed1617cc006b6e66e225868264b4c1aa563dae6b557fb33d6e6dff8e4e4e4050e51a87d0b1f91bda65467f96287ee8d6049a2e99a8518054600360a51b908b161790558051808201909152938816845260038482019081527f672945667f64ce7b1755853bd0c8de4d92f2ded2bdeebd30a972846a04a46806875291905291519151909416909102908416177f26a8d9344e226b269b0d236a40fe5b87efe6af1e7a3c9ff71fb1cccdf3b9399e557f8c53ae70b0aa86068023c633abcdda89c433a8a76949ea111f756c171fa2366390527f8dc63755d617d994eebfba101617bf9b5653d4d567bcd5a055c4d3d1b007cc0b8054919092166001600160a01b031991909116179055506200044d565b80516001600160a01b0381168114620003b357600080fd5b919050565b600080600080600080600060e0888a031215620003d457600080fd5b620003df886200039b565b9650620003ef602089016200039b565b9550620003ff604089016200039b565b94506200040f606089016200039b565b93506200041f608089016200039b565b92506200042f60a089016200039b565b91506200043f60c089016200039b565b905092959891949750929550565b608051612f62620004706000396000818161076a01526117220152612f626000f3fe608060405234801561001057600080fd5b50600436106103425760003560e01c80638440d167116101b8578063ceb68c2311610104578063e0a4edf3116100a2578063ef8d03da1161007c578063ef8d03da14610765578063f39c38a01461078c578063f857ef671461079f578063fc036d7c1461081757600080fd5b8063e0a4edf314610737578063e33c71d01461074a578063e7c512771461075257600080fd5b8063d811ae21116100de578063d811ae21146106f2578063de490aca146106fa578063de8c1b791461070f578063deb20d871461072457600080fd5b8063ceb68c23146106c4578063d013355a146106d7578063d38bfff4146106df57600080fd5b80639fc2c47611610171578063b458dd011161014b578063b458dd0114610678578063b4936a591461068b578063bfb7d4a31461069e578063caa61cb0146106b157600080fd5b80639fc2c47614610648578063a1b770461461065d578063a7bebf9f1461066557600080fd5b80638440d167146105a3578063862a179e146105cf5780638808f66d146105e45780638b9d2940146105f95780638c64ea4a1461062057806397331bf91461063357600080fd5b8063391b6f4e1161029257806362dd471611610230578063732742761161020a578063732742761461058357806374e417d71461058b57806375e48e7e146105935780637de9cd221461059b57600080fd5b806362dd471614610539578063647246041461054c5780636b802bc61461057b57600080fd5b80635594851d1161026c5780635594851d146104d85780635aa6e675146104e05780635ab1bd53146104f35780635dcd6745146104fb57600080fd5b8063391b6f4e146104bf57806348dff373146104c75780634c12c773146104d057600080fd5b80631507a04d116102ff5780632541897f116102d95780632541897f1461047e5780632eeabd8f146104865780633080cef11461049957806338906554146104ac57600080fd5b80631507a04d146103f35780631928b3cb14610406578063238efcbc1461047657600080fd5b806306433b1b1461034757806306fdde031461036f57806309e5d1b7146103845780630a1c187c146103ab57806314adb2f3146103d657806314f675d2146103de575b600080fd5b61035c600080516020612e6d83398151915281565b6040519081526020015b60405180910390f35b61037761082c565b6040516103669190612824565b61035c7f250bebb02a4f564f8ff4a1d2af194d82b25fee33eab79ab5d8256144e0ed0dfe81565b6103be6103b936600461283e565b610899565b6040516001600160a01b039091168152602001610366565b61035c6108b4565b6103f16103ec36600461286c565b6108d2565b005b6103f16104013660046128a5565b610a33565b61045761041436600461283e565b6000908152600460209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160601b03169290910182905291565b604080516001600160a01b039093168352602083019190915201610366565b6103f1610b23565b6103be610bcb565b6103be610494366004612931565b610be4565b6103f16104a736600461295d565b610c15565b6103f16104ba36600461286c565b611144565b6103be6112e4565b61035c60035481565b61035c6112fd565b61035c611316565b6000546103be906001600160a01b031681565b6103be61132f565b61052961050936600461299f565b6001600160a01b0390811660009081526005602052604090205416151590565b6040519015158152602001610366565b6103be6105473660046129bc565b611348565b6103be61055a36600461299f565b6001600160a01b039081166000908152600560205260409020600201541690565b61035c611378565b61035c611391565b6103be6113aa565b6103be6113c3565b6103be6113ee565b61035c6105b136600461299f565b6001600160a01b031660009081526005602052604090206001015490565b61035c600080516020612ecd83398151915281565b61035c600080516020612e8d83398151915281565b61035c7f1629cfbd564ce33f37c84741f82a28dcd353c97db5819722102f8704671969be81565b6103be61062e36600461283e565b611419565b61063b611443565b60405161036691906129f7565b61035c600080516020612e4d83398151915281565b6103be6114a5565b6103f161067336600461283e565b6114be565b6103be610686366004612a44565b611501565b6103f1610699366004612a79565b611532565b6103be6106ac36600461299f565b611593565b6103f16106bf366004612a9e565b6115af565b6103f16106d236600461299f565b611685565b61035c611972565b6103f16106ed36600461299f565b61198b565b6103be611a22565b61035c600080516020612eed83398151915281565b61035c600080516020612f0d83398151915281565b6103f1610732366004612931565b611a3b565b61035c61074536600461283e565b611a58565b6103be611a7a565b6103be610760366004612b2f565b611a93565b6103be7f000000000000000000000000000000000000000000000000000000000000000081565b6001546103be906001600160a01b031681565b6107e26107ad36600461299f565b60056020526000908152604090208054600182015460028301546003909301546001600160a01b039283169391929091169084565b60405161036694939291906001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b61035c600080516020612ead83398151915281565b6040517f596561726e205633205661756c7420526f6c65204d616e6167657200000000006020820152606090603b0160405160208183030381529060405261087390612bcb565b60405160200161088591815260200190565b604051602081830303815290604052905090565b6000908152600460205260409020546001600160a01b031690565b60006108cd600080516020612ecd833981519152611a58565b905090565b600080516020612f0d8339815191526108ea81611ae6565b6001600160a01b038381166000908152600560205260409020541661092a5760405162461bcd60e51b815260040161092190612bef565b60405180910390fd5b6040805180820182526001600160a01b0380861660009081526005602090815293812060020154909116825291810191909152610968908490611b52565b604080518082019091526001600160a01b0383168152600080516020612e8d833981519152600052600460209081527fb33d6e6dff8e4e4e4050e51a87d0b1f91bda65467f96287ee8d6049a2e99a85154600160a01b90046001600160601b0316908201526109d8908490611b52565b6001600160a01b0383811660008181526005602052604080822060020180546001600160a01b0319169487169485179055517f46b03560e5440592db04cf536396abd2d0e1da05cd4bab259a01af406a8686ed9190a3505050565b610a3b611bd6565b6000805b84811015610b1b57858582818110610a5957610a59612c18565b9050602002016020810190610a6e919061299f565b6001600160a01b0380821660009081526005602052604090205491935016610aa85760405162461bcd60e51b815260040161092190612bef565b60405163e2bf56dd60e01b81526001600160a01b0385811660048301526024820185905283169063e2bf56dd90604401600060405180830381600087803b158015610af257600080fd5b505af1158015610b06573d6000803e3d6000fd5b5050505080610b1490612c44565b9050610a3f565b505050505050565b6001546001600160a01b03163314610b735760405162461bcd60e51b81526020600482015260136024820152722170656e64696e6720676f7665726e616e636560681b6044820152606401610921565b6000805460405133926001600160a01b03909216917f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce8091a3600080546001600160a01b03199081163317909155600180549091169055565b60006108cd600080516020612ead833981519152610899565b6000600080516020612eed833981519152610bfe81611ae6565b610c0d84846000600354611c20565b949350505050565b600080516020612eed833981519152610c2d81611ae6565b6000846001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c919190612c5d565b90506000856001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cd3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cfb9190810190612c7a565b6001600160a01b03831660009081526006602052604080822090519293509091610d26908490612ce8565b9081526040805160209281900383019020600089815292529020546001600160a01b031614610db1576001600160a01b038216600090815260066020526040908190209051610d76908390612ce8565b9081526040805160209281900383018120600089815293529120546329ab51bf60e01b82526001600160a01b03166004820152602401610921565b306001600160a01b0316866001600160a01b03166379b989176040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1d9190612c5d565b6001600160a01b031614610e7f57856001600160a01b031663f776bf1f6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b505050505b6000610e98600080516020612e6d833981519152610899565b60405163a237e94d60e01b81526001600160a01b0389811660048301529192509082169063a237e94d90602401602060405180830381865afa158015610ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f069190612d04565b610f6657604051630ab322d960e01b81526001600160a01b038881166004830152821690630ab322d990602401600060405180830381600087803b158015610f4d57600080fd5b505af1158015610f61573d6000803e3d6000fd5b505050505b610f708786612075565b60006001600160a01b0316876001600160a01b0316634fb3ccc56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdd9190612c5d565b6001600160a01b031603610ff457610ff487612324565b604080516080810182526001600160a01b0380861680835260208084018b81528a841685870190815260028054606088019081528f8716600090815260058652898120985189549089166001600160a01b0319918216178a55945160018a0155925191880180549290971691909316179094555160039094019390935581526006909152819020905188919061108b908590612ce8565b90815260408051918290036020908101832060008b8152915290812080546001600160a01b039485166001600160a01b0319918216179091556002805460018101825592527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180548b851692168217905591871691907f65fe7f527479e9a13137b5a7af43efff08bb8e165ff5897ad493bb0362a690c190611133908a815260200190565b60405180910390a350505050505050565b600080516020612f0d83398151915261115c81611ae6565b6001600160a01b03838116600090815260056020526040902054166111935760405162461bcd60e51b815260040161092190612bef565b60006111ac600080516020612ecd833981519152610899565b9050806001600160a01b0316836001600160a01b0316141580156112385750604051634c9ba32160e11b81526001600160a01b038281166004830152851690639937464290602401602060405180830381865afa158015611211573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112359190612d26565b15155b1561126e5761126e846040518060400160405280846001600160a01b0316815260200160006001600160601b0316815250611b52565b604080518082019091526001600160a01b0384168152600080516020612ecd833981519152600052600460209081527fc0f9a12d667a5c774acef575ed1617cc006b6e66e225868264b4c1aa563dae6b54600160a01b90046001600160601b0316908201526112de908590611b52565b50505050565b60006108cd600080516020612ecd833981519152610899565b60006108cd600080516020612ead833981519152611a58565b60006108cd600080516020612e4d833981519152611a58565b60006108cd600080516020612e6d833981519152610899565b6000600080516020612eed83398151915261136281611ae6565b61136e86868686611c20565b9695505050505050565b60006108cd600080516020612f0d833981519152611a58565b60006108cd600080516020612eed833981519152611a58565b60006108cd600080516020612e4d833981519152610899565b60006108cd7f250bebb02a4f564f8ff4a1d2af194d82b25fee33eab79ab5d8256144e0ed0dfe610899565b60006108cd7f1629cfbd564ce33f37c84741f82a28dcd353c97db5819722102f8704671969be610899565b6002818154811061142957600080fd5b6000918252602090912001546001600160a01b0316905081565b6060600280548060200260200160405190810160405280929190818152602001828054801561149b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161147d575b5050505050905090565b60006108cd600080516020612e8d833981519152610899565b6114c6611bd6565b60038190556040518181527f4c5e7edcabd189a3cdd68d6b4890f6b8159bf382e2d11a87aa39851f0377432f9060200160405180910390a150565b6000600080516020612eed83398151915261151b81611ae6565b611529858585600354611c20565b95945050505050565b61153a611bd6565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0385169081179091559051909184917f8c42303edb98aad4f3e4f1a15363dda2db344e9fd66ecff9acf62f770c474fa39190a35050565b600061159e826124a9565b90506115aa82826108d2565b919050565b6115b7611bd6565b600080516020612e8d83398151915282141580156115e35750600080516020612ecd8339815191528214155b61161f5760405162461bcd60e51b815260206004820152600d60248201526c63616e6e6f742075706461746560981b6044820152606401610921565b60008281526004602090815260409182902080546001600160a01b0316600160a01b6001600160601b03861602179055905182815283917ff8a7e043f1e7310711bc663ed81ae8855aa474348c57a6461b9f52a4fa88a94d910160405180910390a25050565b600080516020612f0d83398151915261169d81611ae6565b6001600160a01b03808316600090815260056020908152604091829020825160808101845281548516808252600183015493820193909352600282015490941692840192909252600390910154606083015261170b5760405162461bcd60e51b815260040161092190612bef565b60405163ef54cefd60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015284169063ef54cefd90602401600060405180830381600087803b15801561176e57600080fd5b505af1158015611782573d6000803e3d6000fd5b5050505060006002600160028054905061179c9190612d3f565b815481106117ac576117ac612c18565b9060005260206000200160009054906101000a90046001600160a01b031690508060028360600151815481106117e4576117e4612c18565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905560608501519284168252600590526040902060030155600280548061183357611833612d52565b60008281526020808220830160001990810180546001600160a01b031916905590920190925583516001600160a01b039081168352600690915260408083208151630258294160e41b81529151909392881692632582941092600480820193918290030181865afa1580156118ac573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118d49190810190612c7a565b6040516118e19190612ce8565b908152604080516020928190038301812085840151600090815290845282812080546001600160a01b03199081169091556001600160a01b03891680835260059095529281208054841681556001810182905560028101805490941690935560039092018290557fa40a7d97cd4243d8bcd193dc4d709afc3717750c5996d9e7216d1a5e0288c4949190a250505050565b60006108cd600080516020612e8d833981519152611a58565b611993611bd6565b6001600160a01b0381166119d85760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b6044820152606401610921565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fa443b483867b0f9db5b03913474dd21935ac5ba70fa6c94e3423ba9be157c44b90600090a250565b60006108cd600080516020612f0d833981519152610899565b6000611a46836124a9565b9050611a53838383610c15565b505050565b600090815260046020526040902054600160a01b90046001600160601b031690565b60006108cd600080516020612eed833981519152610899565b6001600160a01b0383166000908152600660205260408082209051611ab9908590612ce8565b90815260408051602092819003830190206000948552909152909120546001600160a01b03169392505050565b6000546001600160a01b0316331480611b185750611b0381610899565b6001600160a01b0316336001600160a01b0316145b611b4f5760405162461bcd60e51b815260206004820152600860248201526708585b1b1bddd95960c21b6044820152606401610921565b50565b80516001600160a01b031615611bd25780516020820151604051632cf7fd8560e01b81526001600160a01b0392831660048201526001600160601b03909116602482015290831690632cf7fd85906044015b600060405180830381600087803b158015611bbe57600080fd5b505af1158015610b1b573d6000803e3d6000fd5b5050565b6000546001600160a01b03163314611c1e5760405162461bcd60e51b815260206004820152600b60248201526a21676f7665726e616e636560a81b6044820152606401610921565b565b600080611c2c85612579565b90506000866001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611c6e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c969190810190612c7a565b82604051602001611ca8929190612d68565b60405160208183030381529060405290506000876001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611cf9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d219190810190612c7a565b83604051602001611d33929190612db8565b6040516020818303038152906040529050611d5b600080516020612e6d833981519152610899565b6001600160a01b03166317bdd312898484308a6040518663ffffffff1660e01b8152600401611d8e959493929190612e02565b6020604051808303816000875af1158015611dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd19190612c5d565b93506000846001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015611e13573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e3b9190810190612c7a565b6001600160a01b038a1660009081526006602052604080822090519293509091611e66908490612ce8565b908152604080516020928190038301902060008c815292529020546001600160a01b031614611ef1576001600160a01b038916600090815260066020526040908190209051611eb6908390612ce8565b908152604080516020928190038301812060008c815293529120546329ab51bf60e01b82526001600160a01b03166004820152602401610921565b6000611efc866124a9565b9050611f088682612075565b611f1186612324565b8715611f2157611f21868961260c565b604080516080810182526001600160a01b03808d1680835260208084018e815286841685870190815260028054606088019081528e8716600090815260058652898120985189549089166001600160a01b0319918216178a55945160018a01559251918801805492909716919093161790945551600390940193909355815260069091528190209051879190611fb8908590612ce8565b90815260408051918290036020908101832060008e8152915290812080546001600160a01b039485166001600160a01b0319918216179091556002805460018101825592527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180548a851692168217905591831691907f65fe7f527479e9a13137b5a7af43efff08bb8e165ff5897ad493bb0362a690c190612060908d815260200190565b60405180910390a35050505050949350505050565b600080516020612eed83398151915260005260046020908152604080518082019091527fd47b3c79bd50e59096d8ce65b63ebf51be417f69055d0030a5934fa136f10d24546001600160a01b0381168252600160a01b90046001600160601b0316918101919091526120e8908390611b52565b600080516020612f0d83398151915260005260046020908152604080518082019091527f8d0e7cff81b8eff0d9b894fecb0fea5bbeb095356aa51bcebdf3c71720e5bb28546001600160a01b0381168252600160a01b90046001600160601b03169181019190915261215b908390611b52565b600080516020612ead83398151915260005260046020908152604080518082019091527f0f0b81d657455a35b8381ada6898e7d534146b34b30517e64f1480e4d241f39d546001600160a01b0381168252600160a01b90046001600160601b0316918101919091526121ce908390611b52565b600080516020612ecd83398151915260005260046020908152604080518082019091527fc0f9a12d667a5c774acef575ed1617cc006b6e66e225868264b4c1aa563dae6b546001600160a01b0381168252600160a01b90046001600160601b031691810191909152612241908390611b52565b600080516020612e4d83398151915260005260046020908152604080518082019091527f26a8d9344e226b269b0d236a40fe5b87efe6af1e7a3c9ff71fb1cccdf3b9399e546001600160a01b0381168252600160a01b90046001600160601b0316918101919091526122b4908390611b52565b604080518082019091526001600160a01b0382168152600080516020612e8d833981519152600052600460209081527fb33d6e6dff8e4e4e4050e51a87d0b1f91bda65467f96287ee8d6049a2e99a85154600160a01b90046001600160601b031690820152611bd2908390611b52565b600061234f7f1629cfbd564ce33f37c84741f82a28dcd353c97db5819722102f8704671969be610899565b90506001600160a01b03811615611bd2576040516354be77d160e11b8152306004820152600860248201526001600160a01b0383169063a97cefa290604401600060405180830381600087803b1580156123a857600080fd5b505af11580156123bc573d6000803e3d6000fd5b50506040516371da8a8d60e01b81526001600160a01b038481166004830152851692506371da8a8d9150602401600060405180830381600087803b15801561240357600080fd5b505af1158015612417573d6000803e3d6000fd5b505060405163e2bf56dd60e01b8152306004820152600860248201526001600160a01b038516925063e2bf56dd9150604401600060405180830381600087803b15801561246357600080fd5b505af1158015612477573d6000803e3d6000fd5b50506040516312b5ad0160e11b81526001600160a01b0385811660048301528416925063256b5a029150602401611ba4565b6000806124d57f250bebb02a4f564f8ff4a1d2af194d82b25fee33eab79ab5d8256144e0ed0dfe610899565b90506001600160a01b038116156125595760405163028d34c960e41b81526001600160a01b0384811660048301528216906328d34c90906024016020604051808303816000875af115801561252e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125529190612c5d565b9150612573565b612570600080516020612e8d833981519152610899565b91505b50919050565b60606000612586836126fb565b600101905060008167ffffffffffffffff8111156125a6576125a6612ac0565b6040519080825280601f01601f1916602001820160405280156125d0576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846125da57509392505050565b6040516354be77d160e11b815230600482015261010060248201526001600160a01b0383169063a97cefa290604401600060405180830381600087803b15801561265557600080fd5b505af1158015612669573d6000803e3d6000fd5b50506040516337f00e8f60e11b8152600481018490526001600160a01b0385169250636fe01d1e9150602401600060405180830381600087803b1580156126af57600080fd5b505af11580156126c3573d6000803e3d6000fd5b505060405163e2bf56dd60e01b815230600482015261010060248201526001600160a01b038516925063e2bf56dd9150604401611ba4565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061273a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612766576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061278457662386f26fc10000830492506010015b6305f5e100831061279c576305f5e100830492506008015b61271083106127b057612710830492506004015b606483106127c2576064830492506002015b600a83106127ce576001015b92915050565b60005b838110156127ef5781810151838201526020016127d7565b50506000910152565b600081518084526128108160208601602086016127d4565b601f01601f19169290920160200192915050565b60208152600061283760208301846127f8565b9392505050565b60006020828403121561285057600080fd5b5035919050565b6001600160a01b0381168114611b4f57600080fd5b6000806040838503121561287f57600080fd5b823561288a81612857565b9150602083013561289a81612857565b809150509250929050565b600080600080606085870312156128bb57600080fd5b843567ffffffffffffffff808211156128d357600080fd5b818701915087601f8301126128e757600080fd5b8135818111156128f657600080fd5b8860208260051b850101111561290b57600080fd5b6020928301965094505085013561292181612857565b9396929550929360400135925050565b6000806040838503121561294457600080fd5b823561294f81612857565b946020939093013593505050565b60008060006060848603121561297257600080fd5b833561297d81612857565b925060208401359150604084013561299481612857565b809150509250925092565b6000602082840312156129b157600080fd5b813561283781612857565b600080600080608085870312156129d257600080fd5b84356129dd81612857565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b81811015612a385783516001600160a01b031683529284019291840191600101612a13565b50909695505050505050565b600080600060608486031215612a5957600080fd5b8335612a6481612857565b95602085013595506040909401359392505050565b60008060408385031215612a8c57600080fd5b82359150602083013561289a81612857565b60008060408385031215612ab157600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612aff57612aff612ac0565b604052919050565b600067ffffffffffffffff821115612b2157612b21612ac0565b50601f01601f191660200190565b600080600060608486031215612b4457600080fd5b8335612b4f81612857565b9250602084013567ffffffffffffffff811115612b6b57600080fd5b8401601f81018613612b7c57600080fd5b8035612b8f612b8a82612b07565b612ad6565b818152876020838501011115612ba457600080fd5b81602084016020830137600060208383010152809450505050604084013590509250925092565b805160208083015191908110156125735760001960209190910360031b1b16919050565b6020808252600f908201526e1d985d5b1d081b9bdd081859191959608a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612c5657612c56612c2e565b5060010190565b600060208284031215612c6f57600080fd5b815161283781612857565b600060208284031215612c8c57600080fd5b815167ffffffffffffffff811115612ca357600080fd5b8201601f81018413612cb457600080fd5b8051612cc2612b8a82612b07565b818152856020838501011115612cd757600080fd5b6115298260208301602086016127d4565b60008251612cfa8184602087016127d4565b9190910192915050565b600060208284031215612d1657600080fd5b8151801515811461283757600080fd5b600060208284031215612d3857600080fd5b5051919050565b818103818111156127ce576127ce612c2e565b634e487b7160e01b600052603160045260246000fd5b60008351612d7a8184602088016127d4565b602d60f81b9083019081528351612d988160018401602088016127d4565b66081e55985d5b1d60ca1b60019290910191820152600801949350505050565b613cbb60f11b815260008351612dd58160028501602088016127d4565b602d60f81b6002918401918201528351612df68160038401602088016127d4565b01600301949350505050565b600060018060a01b03808816835260a06020840152612e2460a08401886127f8565b8381036040850152612e3681886127f8565b959091166060840152505060800152939250505056fe672945667f64ce7b1755853bd0c8de4d92f2ded2bdeebd30a972846a04a468068c53ae70b0aa86068023c633abcdda89c433a8a76949ea111f756c171fa23663e36275342c99ede79a003741503250226904c6a298f8766fdff5fe056b171b70c764ac13dc7e58eb6edf8aad73d30d911cca42d6ee992ed1eec1b0c56476dc024f78afe9dfc9a0cb0441c27b9405070cd2a48b490636a7bdd09f355e33a5d7deeef8b74e4ca2e456a61430d3d94f2b0a4710302ac13b192e2eec36b17440cfc54c1bd391859805757d865ed7b509d4d26733b7a2204f0afcf45fe0d3efa000a5a26469706673582212204f62da56a9b8cd75182336b57a2a001fdacade7867d92e13340daa5b2614253664736f6c63430008120033000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff52000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5200000000000000000000000016388463d60ffe0661cf7f1f31a7d658ac790ff70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2d26d13582324f10c7c3753b8f5fc71011ecf570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff31a1b020c868f6ea3f61eb953344920eeca3af","name":"RoleManager","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_daddy","type":"address"},{"internalType":"address","name":"_brain","type":"address"},{"internalType":"address","name":"_security","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_strategyManager","type":"address"},{"internalType":"address","name":"_registry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"AlreadyDeployed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"debtAllocator","type":"address"},{"indexed":false,"internalType":"uint256","name":"category","type":"uint256"}],"name":"AddedNewVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernance","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernance","type":"address"}],"name":"GovernanceTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"}],"name":"RemovedVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"debtAllocator","type":"address"}],"name":"UpdateDebtAllocator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDefaultProfitMaxUnlock","type":"uint256"}],"name":"UpdateDefaultProfitMaxUnlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newPendingGovernance","type":"address"}],"name":"UpdatePendingGovernance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"position","type":"bytes32"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"UpdatePositionHolder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"position","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"newRoles","type":"uint256"}],"name":"UpdatePositionRoles","type":"event"},{"inputs":[],"name":"ACCOUNTANT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ALLOCATOR_FACTORY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BRAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DADDY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEBT_ALLOCATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KEEPER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REGISTRY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECURITY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRATEGY_MANAGER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_category","type":"uint256"},{"internalType":"address","name":"_debtAllocator","type":"address"}],"name":"addNewVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_category","type":"uint256"}],"name":"addNewVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chad","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultProfitMaxUnlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAccountant","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllVaults","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllocatorFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBrain","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBrainRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"getCategory","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDaddy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDaddyRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"getDebtAllocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDebtAllocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDebtAllocatorRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getKeeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getKeeperRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"getPosition","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"getPositionHolder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_positionId","type":"bytes32"}],"name":"getPositionRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSecurity","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSecurityRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStrategyManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStrategyManagerRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"string","name":"_apiVersion","type":"string"},{"internalType":"uint256","name":"_category","type":"uint256"}],"name":"getVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"isVaultsRoleManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_category","type":"uint256"}],"name":"newVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_category","type":"uint256"},{"internalType":"uint256","name":"_depositLimit","type":"uint256"},{"internalType":"uint256","name":"_profitMaxUnlockTime","type":"uint256"}],"name":"newVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_category","type":"uint256"},{"internalType":"uint256","name":"_depositLimit","type":"uint256"}],"name":"newVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_vaults","type":"address[]"},{"internalType":"address","name":"_holder","type":"address"},{"internalType":"uint256","name":"_role","type":"uint256"}],"name":"removeRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"removeVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newDefaultProfitMaxUnlock","type":"uint256"}],"name":"setDefaultProfitMaxUnlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_position","type":"bytes32"},{"internalType":"address","name":"_newHolder","type":"address"}],"name":"setPositionHolder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_position","type":"bytes32"},{"internalType":"uint256","name":"_newRoles","type":"uint256"}],"name":"setPositionRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"transferGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_debtAllocator","type":"address"}],"name":"updateDebtAllocator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"updateDebtAllocator","outputs":[{"internalType":"address","name":"_newDebtAllocator","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_keeper","type":"address"}],"name":"updateKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vaultConfig","outputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"category","type":"uint256"},{"internalType":"address","name":"debtAllocator","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vaults","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff52000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5200000000000000000000000016388463d60ffe0661cf7f1f31a7d658ac790ff70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2d26d13582324f10c7c3753b8f5fc71011ecf570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff31a1b020c868f6ea3f61eb953344920eeca3af"}