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

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:

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

Errors

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

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

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

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

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

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

Returns the name of the vault shares token.

Returns:

  • The token name

symbol

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

Returns the symbol of the vault shares token.

Returns:

  • The token symbol

asset

function asset() public view override returns (address)

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

Returns:

  • The underlying asset address

totalAssets

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

function totalDeposits() public view returns (uint256)

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

Returns:

  • The total accounted assets

sharePrice

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

function setTreasury(address _treasury) external

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

Parameters:

  • _treasury: New treasury address

setAutopilotEnabled

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

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

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

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

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

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

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

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

function _organizeWithdrawalQueue() internal

Reorganizes withdrawal queue by removing gaps and maintaining relative order.

_revokeStrategy

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

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

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

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

Returns value plus one.

Parameters:

  • x: Value to increment

Returns:

  • Incremented value

_sub0

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

function _underlyingDecimals() internal view override returns (uint8)

Returns decimals of the underlying token.

Returns:

  • Number of decimals

_decimalsOffset

function _decimalsOffset() internal pure override returns (uint8)

Returns decimal offset used to prevent inflation attacks.

Returns:

  • Decimal offset value (6)

_totalAssets

function _totalAssets() internal view returns (uint256)

Calculates total assets including idle funds and strategy positions.

Returns:

  • Total assets under management

_totalDeposits

function _totalDeposits() internal view returns (uint256)

Returns sum of idle assets and total debt.

Returns:

  • Total deposited assets

_deposit

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

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

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

Last updated