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 depositreceiver
: 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 assetsassets
: Amount of assets to depositdeadline
: Timestamp until which the permit is validv
: Signature parameterr
: Signature parameters
: Signature parameterreceiver
: 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 mintreceiver
: 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 assetsshares
: Amount of shares to mintdeadline
: Timestamp until which the permit is validv
: Signature parameterr
: Signature parameters
: Signature parameterreceiver
: 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 withdrawreceiver
: Address to receive the assetsowner
: 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 redeemreceiver
: Address to receive the assetsowner
: 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 adddebtRatio
: Percentage of vault's total assets that strategy can manage (in BPS)maxDebtPerHarvest
: Maximum debt the strategy can take on in a single harvestminDebtPerHarvest
: Minimum debt the strategy should take in a single harvestperformanceFee
: 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 updatenewDebtRatio
: New debt ratio (in BPS)newMaxDebtPerHarvest
: New maximum debt per harvestnewMinDebtPerHarvest
: New minimum debt per harvestnewPerformanceFee
: 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 profitunrealizedGain
: Unrealized profitloss
: Amount of lossesdebtPayment
: Amount of debt being repaidmanagementFeeReceiver
: 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 strategysuccess
: Whether the harvest was successfulreason
: 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 lossloss
: 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 forgain
: Amount of profit to assess fees onmanagementFeeReceiver
: 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 revokestrategyDebtRatio
: 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 sharesamount
: 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 checkb
: 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 fromb
: 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 assetsto
: Address receiving sharesassets
: Amount of assets being depositedshares
: 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 withdrawalto
: Address receiving assetsowner
: Owner of the sharesassets
: 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 redemptionto
: Address receiving assetsowner
: Owner of the sharesshares
: Amount of shares to redeem
Returns:
Amount of assets returned
Last updated