# MaxApyVault

## Overview

The MaxApyVault is an ERC4626-compatible vault contract that serves as the core component of the MaxAPY Protocol. It manages user deposits and strategy allocations to generate yield. The vault accepts deposits of a specific underlying asset, issues share to depositors, and allocates the funds across various yield-generating strategies.

## Constants

```solidity
uint256 public constant MAXIMUM_STRATEGIES = 20;       // Maximum number of strategies the vault can manage
uint256 public constant MAX_BPS = 10_000;             // Base points scale (100%)
uint256 public constant SECS_PER_YEAR = 31_556_952;   // Seconds in a year (365.2425 days)
uint256 public constant AUTOPILOT_HARVEST_INTERVAL = 1 weeks;  // Interval between automated harvests
```

Access Control Roles:

```solidity
uint256 public constant ADMIN_ROLE = _ROLE_0;
uint256 public constant EMERGENCY_ADMIN_ROLE = _ROLE_1;
uint256 public constant STRATEGY_ROLE = _ROLE_2;
```

## Errors

```solidity
error QueueIsFull();                            // Withdrawal queue has reached maximum capacity
error VaultInEmergencyShutdownMode();           // Operation not allowed during emergency shutdown
error StrategyInEmergencyExitMode();            // Strategy is in emergency exit mode
error InvalidZeroAddress();                      // Zero address provided where not allowed
error StrategyAlreadyActive();                  // Attempt to add already active strategy
error StrategyNotActive();                      // Operation attempted on inactive strategy
error InvalidStrategyVault();                   // Strategy's vault address doesn't match
error InvalidStrategyUnderlying();              // Strategy's underlying asset doesn't match
error InvalidDebtRatio();                       // Debt ratio exceeds maximum allowed
error InvalidMinDebtPerHarvest();               // Invalid minimum debt per harvest value
error InvalidPerformanceFee();                  // Performance fee exceeds maximum allowed
error InvalidManagementFee();                   // Management fee exceeds maximum allowed
error StrategyDebtRatioAlreadyZero();          // Strategy's debt ratio is already zero
error InvalidQueueOrder();                      // Invalid withdrawal queue ordering
error VaultDepositLimitExceeded();             // Deposit would exceed vault's limit
error InvalidZeroAmount();                      // Zero amount provided where not allowed
error InvalidZeroShares();                      // Zero shares amount where not allowed
error LossGreaterThanStrategyTotalDebt();      // Reported loss exceeds strategy's total debt
error InvalidReportedGainAndDebtPayment();      // Invalid gain and debt payment reported
error FeesAlreadyAssesed();                    // Fees have already been assessed
```

## Events

### Strategy Management Events

```solidity
event StrategyAdded(
    address indexed newStrategy,
    uint16 strategyDebtRatio,
    uint128 strategyMaxDebtPerHarvest,
    uint128 strategyMinDebtPerHarvest,
    uint16 strategyPerformanceFee
);

event StrategyRemoved(address indexed strategy);
event StrategyRevoked(address indexed strategy);
event StrategyExited(address indexed strategy, uint256 withdrawn);

event StrategyUpdated(
    address indexed strategy,
    uint16 newDebtRatio,
    uint128 newMaxDebtPerHarvest,
    uint128 newMinDebtPerHarvest,
    uint16 newPerformanceFee
);

event StrategyReported(
    address indexed strategy,
    uint256 unrealizedGain,
    uint256 loss,
    uint256 debtPayment,
    uint128 strategyTotalUnrealizedGain,
    uint128 strategyTotalLoss,
    uint128 strategyTotalDebt,
    uint256 credit,
    uint16 strategyDebtRatio
);
```

### Configuration Events

```solidity
event EmergencyShutdownUpdated(bool emergencyShutdown);
event AutopilotEnabled(bool isEnabled);
event WithdrawalQueueUpdated(address[20] withdrawalQueue);
event PerformanceFeeUpdated(uint16 newPerformanceFee);
event ManagementFeeUpdated(uint256 newManagementFee);
event DepositLimitUpdated(uint256 newDepositLimit);
event TreasuryUpdated(address treasury);
```

### Operation Events

```solidity
event WithdrawFromStrategy(address indexed strategy, uint128 strategyTotalDebt, uint128 loss);
event FeesReported(uint256 managementFee, uint16 performanceFee, uint256 strategistFee, uint256 duration);
event ForceHarvestFailed(address indexed strategy, bytes reason);
```

## State Variables

```solidity
bool public emergencyShutdown;                  // Emergency shutdown state
bool public autoPilotEnabled;                   // Automated harvesting state
uint8 private immutable _decimals;              // Underlying token decimals
uint8 public nexHarvestStrategyIndex;           // Next strategy index to harvest
uint256 public depositLimit;                    // Maximum total assets limit
uint256 public debtRatio;                       // Total debt ratio across strategies (in BPS)
uint256 public totalIdle;                       // Tokens held in vault
uint256 public totalDebt;                       // Total tokens allocated to strategies
uint256 public lastReport;                      // Timestamp of last strategy report
uint256 public performanceFee;                  // Performance fee rate (in BPS)
uint256 public managementFee;                   // Management fee rate (in BPS)
address public treasury;                        // Fee recipient address

mapping(address => StrategyData) public strategies;  // Strategy data mapping
address[MAXIMUM_STRATEGIES] public withdrawalQueue;   // Strategy withdrawal order

string private _name;                           // Vault shares token name
string private _symbol;                         // Vault shares token symbol
address private immutable _underlyingAsset;     // Underlying asset address
```

## Functions

### Basic View Functions

### name

```solidity
function name() public view override returns (string memory)
```

Returns the name of the vault shares token.

Returns:

* The token name

### symbol

```solidity
function symbol() public view override returns (string memory)
```

Returns the symbol of the vault shares token.

Returns:

* The token symbol

### asset

```solidity
function asset() public view override returns (address)
```

Returns the address of the underlying token that the vault accepts.

Returns:

* The underlying asset address

### totalAssets

```solidity
function totalAssets() public view override returns (uint256)
```

Returns total assets managed by vault, including idle funds and assets deployed in strategies.

Returns:

* The total assets under management

### totalDeposits

```solidity
function totalDeposits() public view returns (uint256)
```

Returns the sum of idle assets and debt allocated to strategies.

Returns:

* The total accounted assets

### sharePrice

```solidity
function sharePrice() external view returns (uint256)
```

Returns the current price of one vault share regarding the underlying asset.

Returns:

* The current share price

### Asset/Share Conversion Functions

### convertToShares

```solidity
function convertToShares(uint256 assets) public view override returns (uint256)
```

Calculates how many shares would be minted for a given amount of assets.

Parameters:

* `assets`: Amount of underlying assets to convert

Returns:

* The equivalent amount of shares

### convertToAssets

```solidity
function convertToAssets(uint256 shares) public view override returns (uint256)
```

Calculates how many underlying assets a given amount of shares represents.

Parameters:

* `shares`: Amount of shares to convert

Returns:

* The equivalent amount of assets

### Deposit Limit Functions

### maxDeposit

```solidity
function maxDeposit(address to) public view override returns (uint256)
```

Calculates the maximum amount of assets that can be deposited.

Parameters:

* `to`: Address that would receive the shares (unused in calculation)

Returns:

* Maximum deposit amount allowed

### maxMint

```solidity
function maxMint(address to) public view override returns (uint256)
```

Calculates the maximum amount of shares that can be minted.

Parameters:

* `to`: Address that would receive the shares (unused in calculation)

Returns:

* Maximum shares that can be minted

### maxWithdraw

```solidity
function maxWithdraw(address owner) public view override returns (uint256)
```

Returns the maximum amount of assets that an address can withdraw.

Parameters:

* `owner`: Address of the shares owner

Returns:

* Maximum assets that can be withdrawn

### Preview Functions

### previewMint

```solidity
function previewMint(uint256 shares) public view override returns (uint256)
```

Simulates the amount of assets needed to mint a specific amount of shares.

Parameters:

* `shares`: The amount of shares to mint

Returns:

* The amount of assets required

### previewWithdraw

```solidity
function previewWithdraw(uint256 assets) public view override returns (uint256)
```

Simulates the amount of shares needed to withdraw a specific amount of assets.

Parameters:

* `assets`: The amount of assets to withdraw

Returns:

* The amount of shares required

### previewRedeem

```solidity
function previewRedeem(uint256 shares) public view override returns (uint256)
```

Simulates the amount of assets that would be received when redeeming shares.

Parameters:

* `shares`: The amount of shares to redeem

Returns:

* The amount of assets that would be received

### Strategy View Functions

### creditAvailable

```solidity
function creditAvailable(address strategy) external view returns (uint256)
```

Returns the amount of additional funds a strategy can borrow from the vault.

Parameters:

* `strategy`: The strategy address to check

Returns:

* The amount of credit available

### debtOutstanding

```solidity
function debtOutstanding(address strategy) external view returns (uint256)
```

Returns the amount of debt that a strategy needs to repay to the vault.

Parameters:

* `strategy`: The strategy address to check

Returns:

* The amount of outstanding debt

### getStrategyTotalDebt

```solidity
function getStrategyTotalDebt(address strategy) external view returns (uint256)
```

Returns the total debt allocated to a strategy.

Parameters:

* `strategy`: The strategy address to check

Returns:

* The strategy's total debt

### Deposit Functions

### deposit

```solidity
function deposit(uint256 assets, address receiver) public returns (uint256 shares)
```

Deposits underlying assets into the vault and mints shares to the receiver. Only possible when vault is not in emergency shutdown.

Parameters:

* `assets`: Amount of underlying assets to deposit
* `receiver`: Address to receive the minted shares

Returns:

* Amount of shares minted

### depositWithPermit

```solidity
function depositWithPermit(
    address owner,
    uint256 assets,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s,
    address receiver
) public returns (uint256 shares)
```

Deposits assets using an EIP-2612 permit for approval. Prevents extra approve transaction.

Parameters:

* `owner`: Owner of the assets
* `assets`: Amount of assets to deposit
* `deadline`: Timestamp until which the permit is valid
* `v`: Signature parameter
* `r`: Signature parameter
* `s`: Signature parameter
* `receiver`: Address to receive the shares

Returns:

* Amount of shares minted

### mint

```solidity
function mint(uint256 shares, address receiver) public returns (uint256 assets)
```

Mints an exact amount of shares by depositing the necessary amount of assets.

Parameters:

* `shares`: Amount of shares to mint
* `receiver`: Address to receive the shares

Returns:

* Amount of assets deposited

### mintWithPermit

```solidity
function mintWithPermit(
    address owner,
    uint256 shares,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s,
    address receiver
) public returns (uint256 assets)
```

Mints exact shares using an EIP-2612 permit for approval.

Parameters:

* `owner`: Owner of the assets
* `shares`: Amount of shares to mint
* `deadline`: Timestamp until which the permit is valid
* `v`: Signature parameter
* `r`: Signature parameter
* `s`: Signature parameter
* `receiver`: Address to receive the shares

Returns:

* Amount of assets deposited

### Withdrawal Functions

### withdraw

```solidity
function withdraw(
    uint256 assets,
    address receiver,
    address owner
) public returns (uint256 shares)
```

Withdraws exact assets by burning the required amount of shares.

Parameters:

* `assets`: Amount of assets to withdraw
* `receiver`: Address to receive the assets
* `owner`: Owner of the shares

Returns:

* Amount of shares burned

### redeem

```solidity
function redeem(
    uint256 shares,
    address receiver,
    address owner
) public returns (uint256 assets)
```

Burns exact shares for underlying assets.

Parameters:

* `shares`: Amount of shares to redeem
* `receiver`: Address to receive the assets
* `owner`: Owner of the shares

Returns:

* Amount of assets withdrawn

### Strategy Management Functions

### addStrategy

```solidity
function addStrategy(
    address strategy,
    uint256 debtRatio,
    uint256 maxDebtPerHarvest,
    uint256 minDebtPerHarvest,
    uint256 performanceFee
) external
```

Adds a new strategy to the vault. Can only be called by admin and not during emergency shutdown.

Parameters:

* `strategy`: Address of the strategy to add
* `debtRatio`: Percentage of vault's total assets that strategy can manage (in BPS)
* `maxDebtPerHarvest`: Maximum debt the strategy can take on in a single harvest
* `minDebtPerHarvest`: Minimum debt the strategy should take in a single harvest
* `performanceFee`: Performance fee for the strategy (in BPS)

### removeStrategy

```solidity
function removeStrategy(address strategy) external
```

Removes a strategy from the vault's withdrawal queue. Can only be called by admin and not during emergency shutdown.

Parameters:

* `strategy`: Address of the strategy to remove

### revokeStrategy

```solidity
function revokeStrategy(address strategy) external
```

Revokes a strategy by setting its debt ratio to 0 and preventing future deposits. Can only be called by admin.

Parameters:

* `strategy`: Address of the strategy to revoke

### exitStrategy

```solidity
function exitStrategy(address strategy) external
```

Fully exits a strategy by liquidating all positions and removing it from the withdrawal queue. Can only be called by admin.

Parameters:

* `strategy`: Address of the strategy to exit

### updateStrategyData

```solidity
function updateStrategyData(
    address strategy,
    uint256 newDebtRatio,
    uint256 newMaxDebtPerHarvest,
    uint256 newMinDebtPerHarvest,
    uint256 newPerformanceFee
) external
```

Updates a strategy's configuration parameters. Can only be called by admin.

Parameters:

* `strategy`: Address of the strategy to update
* `newDebtRatio`: New debt ratio (in BPS)
* `newMaxDebtPerHarvest`: New maximum debt per harvest
* `newMinDebtPerHarvest`: New minimum debt per harvest
* `newPerformanceFee`: New performance fee (in BPS)

### Reporting Functions

### report

```solidity
function report(
    uint128 realizedGain,
    uint128 unrealizedGain,
    uint128 loss,
    uint128 debtPayment,
    address managementFeeReceiver
) external returns (uint256)
```

Reports strategy performance and handles profit/loss accounting. Can only be called by strategies.

Parameters:

* `realizedGain`: Realized profit
* `unrealizedGain`: Unrealized profit
* `loss`: Amount of losses
* `debtPayment`: Amount of debt being repaid
* `managementFeeReceiver`: Address to receive management fees

Returns:

* Updated debt outstanding

### Configuration Functions

### setWithdrawalQueue

```solidity
function setWithdrawalQueue(address[MAXIMUM_STRATEGIES] calldata queue) external
```

Sets the order of strategies for withdrawals. Can only be called by admin.

Parameters:

* `queue`: Array of strategy addresses in withdrawal order

### setPerformanceFee

```solidity
function setPerformanceFee(uint256 _performanceFee) external
```

Updates the vault's performance fee. Can only be called by admin.

Parameters:

* `_performanceFee`: New performance fee (in BPS)

### setManagementFee

```solidity
function setManagementFee(uint256 _managementFee) external
```

Updates the vault's management fee. Can only be called by admin.

Parameters:

* `_managementFee`: New management fee (in BPS)

### setDepositLimit

```solidity
function setDepositLimit(uint256 _depositLimit) external
```

Sets the maximum total assets the vault can accept. Can only be called by admin.

Parameters:

* `_depositLimit`: New deposit limit

### setEmergencyShutdown

```solidity
function setEmergencyShutdown(bool _emergencyShutdown) external
```

Enables/disables emergency shutdown mode. Can only be called by emergency admin.

Parameters:

* `_emergencyShutdown`: True to enable shutdown, false to disable

### setTreasury

```solidity
function setTreasury(address _treasury) external
```

Updates the treasury address that receives fees. Can only be called by admin.

Parameters:

* `_treasury`: New treasury address

### setAutopilotEnabled

```solidity
function setAutopilotEnabled(bool _autoPilotEnabled) external
```

Enables/disables automated strategy harvesting. Can only be called by admin.

Parameters:

* `_autoPilotEnabled`: True to enable autopilot, false to disable

### setAutoPilot

```solidity
function setAutoPilot(bool _autoPilot) external
```

Sets autopilot mode for a specific strategy. Can only be called by strategies.

Parameters:

* `_autoPilot`: True to enable autopilot for the strategy

### Internal Functions

### \_forceOneHarvest

```solidity
function _forceOneHarvest(address harvester) internal returns (address strategy, bool success, bytes memory reason)
```

Forces a harvest of the next strategy in autopilot mode.

Parameters:

* `harvester`: Address that will receive extra shares for harvesting

Returns:

* `strategy`: Address of the harvested strategy
* `success`: Whether the harvest was successful
* `reason`: Error reason if harvest failed

### \_reportLoss

```solidity
function _reportLoss(address strategy, uint256 loss) internal
```

Handles strategy loss reporting by adjusting debt ratios and total debt.

Parameters:

* `strategy`: Strategy reporting the loss
* `loss`: Amount of loss to report

### \_assessFees

```solidity
function _assessFees(address strategy, uint256 gain, address managementFeeReceiver) internal returns (uint256)
```

Calculates and distributes performance, management, and strategist fees.

Parameters:

* `strategy`: Strategy the fees are being assessed for
* `gain`: Amount of profit to assess fees on
* `managementFeeReceiver`: Address to receive management fees

Returns:

* Total amount of fees assessed

### \_creditAvailable

```solidity
function _creditAvailable(address strategy) internal view returns (uint256)
```

Calculates available credit line for a strategy.

Parameters:

* `strategy`: Strategy to check credit for

Returns:

* Amount of credit available

### \_computeDebtLimit

```solidity
function _computeDebtLimit(uint256 _debtRatio, uint256 totalAssets_) internal pure returns (uint256 debtLimit)
```

Calculates maximum debt limit based on debt ratio and total assets.

Parameters:

* `_debtRatio`: Debt ratio to use (in BPS)
* `totalAssets_`: Total assets to base calculation on

Returns:

* Calculated debt limit

### \_debtOutstanding

```solidity
function _debtOutstanding(address strategy) internal view returns (uint256)
```

Calculates how much debt a strategy needs to pay back.

Parameters:

* `strategy`: Strategy to check debt for

Returns:

* Amount of outstanding debt

### \_organizeWithdrawalQueue

```solidity
function _organizeWithdrawalQueue() internal
```

Reorganizes withdrawal queue by removing gaps and maintaining relative order.

### \_revokeStrategy

```solidity
function _revokeStrategy(address strategy, uint256 strategyDebtRatio) internal
```

Internal function to revoke a strategy and update debt ratios.

Parameters:

* `strategy`: Strategy to revoke
* `strategyDebtRatio`: Current debt ratio of the strategy

### \_issueSharesForAmount

```solidity
function _issueSharesForAmount(address to, uint256 amount) internal returns (uint256 shares)
```

Calculates and mints shares for a given amount of assets.

Parameters:

* `to`: Address to receive shares
* `amount`: Amount of assets to convert to shares

Returns:

* Amount of shares minted

### Helper Functions

### *eitherIsZero*

```solidity
function _eitherIsZero_(uint256 a, uint256 b) internal pure returns (bool)
```

Checks if either of two values is zero.

Parameters:

* `a`: First value to check
* `b`: Second value to check

Returns:

* True if either value is zero

### *inc*

```solidity
function _inc_(uint256 x) internal pure returns (uint256)
```

Returns value plus one.

Parameters:

* `x`: Value to increment

Returns:

* Incremented value

### \_sub0

```solidity
function _sub0(uint256 a, uint256 b) internal pure returns (uint256)
```

Safely subtracts b from a, returning 0 if result would be negative.

Parameters:

* `a`: Value to subtract from
* `b`: Value to subtract

Returns:

* Result of subtraction or 0

### ERC4626 Override Functions

### \_underlyingDecimals

```solidity
function _underlyingDecimals() internal view override returns (uint8)
```

Returns decimals of the underlying token.

Returns:

* Number of decimals

### \_decimalsOffset

```solidity
function _decimalsOffset() internal pure override returns (uint8)
```

Returns decimal offset used to prevent inflation attacks.

Returns:

* Decimal offset value (6)

### \_totalAssets

```solidity
function _totalAssets() internal view returns (uint256)
```

Calculates total assets including idle funds and strategy positions.

Returns:

* Total assets under management

### \_totalDeposits

```solidity
function _totalDeposits() internal view returns (uint256)
```

Returns sum of idle assets and total debt.

Returns:

* Total deposited assets

### \_deposit

```solidity
function _deposit(address by, address to, uint256 assets, uint256 shares) internal override
```

Internal deposit implementation with additional checks.

Parameters:

* `by`: Address depositing assets
* `to`: Address receiving shares
* `assets`: Amount of assets being deposited
* `shares`: Amount of shares to mint

### \_withdraw

```solidity
function _withdraw(address by, address to, address owner, uint256 assets) private returns (uint256 shares)
```

Internal withdraw implementation handling liquidations.

Parameters:

* `by`: Address initiating withdrawal
* `to`: Address receiving assets
* `owner`: Owner of the shares
* `assets`: Amount of assets to withdraw

Returns:

* Amount of shares burned

### \_redeem

```solidity
function _redeem(address by, address to, address owner, uint256 shares) private returns (uint256 assets)
```

Internal redeem implementation handling liquidations.

Parameters:

* `by`: Address initiating redemption
* `to`: Address receiving assets
* `owner`: Owner of the shares
* `shares`: Amount of shares to redeem

Returns:

* Amount of assets returned


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://devs.maxapy.io/maxapy-erc4626/vault/maxapyvault.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
