Vault
Inherits: ERC4626, Multicall, AccessControlDefaultAdminRules, ReentrancyGuard
Author: Molecular Labs
Vault contract that can allocate a single lender asset over various isolated lending pairs on Ion Protocol. This contract is a fork of the Metamorpho contract licnesed under GPL-2.0 with changes to administrative logic, underlying data structures, and lending interactions to be made compatible with Ion Protocol.
State Variables
OWNER_ROLE
ALLOCATOR_ROLE
IDLE
DECIMALS_OFFSET
ION_POOL_SUPPLY_CAP_SLOT
ION_POOL_LIQUIDITY_SLOT
BASE_ASSET
MAX_SUPPORTED_MARKETS
supportedMarkets
supplyQueue
withdrawQueue
feeRecipient
feePercentage
lastTotalAssets
caps
Functions
constructor
updateFeePercentage
Updates the fee percentage.
Input must be in [RAY]. Ex) 2% would be 0.02e27.
Parameters
Name | Type | Description |
---|---|---|
|
| The percentage of the interest accrued to take as a management fee. |
updateFeeRecipient
Updates the fee recipient.
Parameters
Name | Type | Description |
---|---|---|
|
| The recipient address of the shares minted as fees. |
addSupportedMarkets
Add markets that can be supplied and withdrawn from.
Elements in supportedMarkets
must be a valid IonPool or an IDLE address. Valid IonPools require the base asset to be the same. Duplicate addition to the EnumerableSet will revert. The allocationCaps of the new markets being introduced must be set.
Parameters
Name | Type | Description |
---|---|---|
|
| Array of new markets to be added. |
|
| Array of allocation caps for only the markets to be added. |
|
| Desired supply queue of IonPools for all resulting supported markets. |
|
| Desired withdraw queue of IonPools for all resulting supported markets. |
_addSupportedMarkets
removeSupportedMarkets
Removes a supported market and updates the supply and withdraw queues without the removed market.
The allocationCap values of the markets being removed are automatically deleted. Whenever a market is removed, the queues must be updated without the removed market.
Parameters
Name | Type | Description |
---|---|---|
|
| Markets being removed. |
|
| Desired supply queue of all supported markets after the removal. |
|
| Desired withdraw queue of all supported markets after the removal. |
updateSupplyQueue
Update the order of the markets in which user deposits are supplied.
Each IonPool in the queue must be part of the supportedMarkets
set.
Parameters
Name | Type | Description |
---|---|---|
|
| The new supply queue ordering. |
_updateSupplyQueue
updateWithdrawQueue
Update the order of the markets in which the deposits are withdrawn.
The IonPool in the queue must be part of the supportedMarkets
set.
Parameters
Name | Type | Description |
---|---|---|
|
| The new withdraw queue ordering. |
_updateWithdrawQueue
_validateQueueInput
*The input array contains ordered IonPools.
Must not contain duplicates.
Must be the same length as the
supportedMarkets
array.Must not contain indices that are out of bounds of the
supportedMarkets
EnumerableSet's underlying array. The above rule enforces that the queue must have all and only the elements in thesupportedMarkets
set.*
Parameters
Name | Type | Description |
---|---|---|
|
| The queue being validated. |
updateAllocationCaps
Update allocation caps for specified IonPools or the IDLE pool.
The allocation caps are applied to pools in the order of the array within supportedMarkets
. The elements inside ionPools
must exist in supportedMarkets
. To update the IDLE
pool, use the IDLE
constant address.
Parameters
Name | Type | Description |
---|---|---|
|
| The array of IonPools whose caps will be updated. |
|
| The array of new allocation caps to be applied. |
reallocate
Reallocates the base asset supply position across the specified IonPools. This call will revert if the resulting allocation in an IonPool violates the pool's supply cap.
*Depending on the order of deposits and withdrawals to and from markets, the function could revert if there is not enough assets withdrawn to deposit later in the loop. A key invariant is that the total assets withdrawn should be equal to the total assets supplied. Otherwise, revert.
Negative value indicates a withdrawal.
Positive value indicates a supply.*
Parameters
Name | Type | Description |
---|---|---|
|
| Array that indicates how much to deposit or withdraw from each market. |
accrueFee
Manually accrues fees and mints shares to the fee recipient.
_supplyToIonPool
Iterates through the supply queue to deposit the desired amount of assets. Reverts if the deposit amount cannot be filled due to the allocation cap or the supply cap.
External functions calling this must be non-reentrant in case the underlying IonPool implements callback logic.
Parameters
Name | Type | Description |
---|---|---|
|
| The amount of assets that will attempt to be supplied. |
_withdrawFromIonPool
Iterates through the withdraw queue to withdraw the desired amount of assets. Will revert if there is not enough liquidity or if trying to withdraw more than the caller owns.
External functions calling this must be non-reentrant in case the underlying IonPool implements callback logic.
Parameters
Name | Type | Description |
---|---|---|
|
| The desired amount of assets to be withdrawn. |
deposit
Transfers the specified amount of assets from the sender, supplies into the underlying IonPool markets, and mints a corresponding amount of shares.
All incoming deposits are deposited in the order specified in the deposit queue.
Parameters
Name | Type | Description |
---|---|---|
|
| Amount of tokens to be deposited. |
|
| The address to receive the minted shares. |
mint
Mints the specified amount of shares and deposits a corresponding amount of assets.
Converts the shares to assets and iterates through the deposit queue to allocate the deposit across the supported markets.
Parameters
Name | Type | Description |
---|---|---|
|
| The exact amount of shares to be minted. |
|
| The address to receive the minted shares. |
withdraw
Withdraws specified amount of assets from IonPools and sends them to the receiver in exchange for burning the owner's vault shares.
All withdraws are withdrawn in the order specified in the withdraw queue. The owner needs to approve the caller to spend their shares.
Parameters
Name | Type | Description |
---|---|---|
|
| The exact amount of assets to be transferred out. |
|
| The receiver of the assets transferred. |
|
| The owner of the vault shares. |
redeem
Redeems the exact amount of shares and receives a corresponding amount of assets.
After withdrawing assets
, the user gets exact assets
out. But in the IonPool, the resulting total underlying claim may have decreased by a bit above the assets
amount due to rounding in the pool's favor. In that case, the resulting totalAssets()
will be smaller than just the newTotalAssets - assets
. Predicting the exact resulting totalAssets() requires knowing how much liquidity is being withdrawn from each pool, which is not possible to know until the actual iteration on the withdraw queue. So we acknowledge the dust difference here. If the lastTotalAssets
is slightly greater than the actual totalAssets
, the impact will be that the calculated interest accrued during fee distribution will be slightly less than the true value.
Parameters
Name | Type | Description |
---|---|---|
|
| The exact amount of shares to be burned and redeemed. |
|
| The address that receives the transferred assets. |
|
| The address that holds the shares to be redeemed. |
decimals
Returns the decimals places of the token.
maxDeposit
Returns the maximum amount of assets that the vault can supply on Ion.
The max deposit amount is limited by the vault's allocation cap and the underlying IonPools' supply caps.
Returns
Name | Type | Description |
---|---|---|
|
| The max amount of assets that can be supplied. |
maxMint
Returns the maximum amount of vault shares that can be minted.
Max mint is limited by the max deposit based on the Vault's allocation caps and the IonPools' supply caps. The conversion from max suppliable assets to shares preempts the shares minted from fee accrual.
Returns
Name | Type | Description |
---|---|---|
|
| The max amount of shares that can be minted. |
maxWithdraw
Returns the maximum amount of assets that can be withdrawn.
Max withdraw is limited by the owner's shares and the liquidity available to be withdrawn from the underlying IonPools. The max withdrawable claim is inclusive of accrued interest and the extra shares minted to the fee recipient.
Parameters
Name | Type | Description |
---|---|---|
|
| The address that holds the assets. |
Returns
Name | Type | Description |
---|---|---|
|
| The max amount of assets that can be withdrawn. |
maxRedeem
Calculates the total withdrawable amount based on the available liquidity in the underlying pools and converts it to redeemable shares.
Max redeem is derived from Γ§onverting the _maxWithdraw
to shares. The conversion takes into account the total supply and total assets inclusive of accrued interest and the extra shares minted to the fee recipient.
Parameters
Name | Type | Description |
---|---|---|
|
| The address that holds the shares. |
Returns
Name | Type | Description |
---|---|---|
|
| The max amount of shares that can be withdrawn. |
totalAssets
Returns the total claim that the vault has across all supported IonPools.
IonPool.balanceOf
returns the rebasing balance of the lender receipt token that is pegged 1:1 to the underlying supplied asset.
Returns
Name | Type | Description |
---|---|---|
|
| The total assets held on the contract and inside the underlying pools by this vault. |
previewDeposit
Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given current on-chain conditions.
Inclusive of manager fee.
previewMint
Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given current on-chain conditions.
Inclusive of manager fee.
previewWithdraw
Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, given current on-chain conditions.
Inclusive of manager fee.
previewRedeem
Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, given current on-chain conditions.
Inclusive of manager fee.
_decimalsOffset
_deposit
_withdraw
_maxDeposit
_maxWithdraw
_accrueFee
_accruedFeeShares
The total accrued vault revenue is the difference in the total iToken holdings from the last accrued timestamp and now.
_convertToSharesWithFees
NOTE The IERC4626 natspec recommends that the _convertToAssets
and _convertToShares
"MUST NOT be inclusive of any fees that are charged against assets in the Vault." However, all deposit/mint/withdraw/redeem flow will accrue fees before processing user requests, so manager fee must be accounted for to accurately reflect the resulting state. All preview functions will rely on this WithFees
version of the _convertTo
function.
_convertToAssetsWithFees
NOTE The IERC4626 natspec recommends that the _convertToAssets
and _convertToShares
"MUST NOT be inclusive of any fees that are charged against assets in the Vault." However, all deposit/mint/withdraw/redeem flow will accrue fees before processing user requests, so manager fee must be accounted for to accurately reflect the resulting state. All preview functions will rely on this WithFees
version of the _convertTo
function.
_convertToSharesWithTotals
Returns the amount of shares that the vault would exchange for the amount of assets
provided. This function is used to calculate the conversion between shares and assets with parameterizable total supply and total assets variables.
_convertToAssetsWithTotals
Returns the amount of assets that the vault would exchange for the amount of shares
provided. This function is used to calculate the conversion between shares and assets with parameterizable total supply and total assets variables.
_updateLastTotalAssets
_zeroFloorSub
_simulateWithdrawIon
Emulates the actual _withdrawFromIonPool
accounting to predict accurately how much of the input assets will be left after withdrawing as much as it can. The difference between this return value and the input assets
is the exact amount that will be withdrawn.
Returns
Name | Type | Description |
---|---|---|
|
| The remaining assets to be withdrawn. NOT the amount of assets that were withdrawn. |
_withdrawable
The max amount of assets withdrawable from a given IonPool considering the vault's claim and the available liquidity. A minimum of this contract's total claim on the underlying and the available liquidity in the pool.
Returns
Name | Type | Description |
---|---|---|
|
| The max amount of assets withdrawable from this IonPool. |
_depositable
The max amount of assets depositable to a given IonPool. Depositing the minimum between the two diffs ensures that the deposit will not violate the allocation cap or the supply cap.
Returns
Name | Type | Description |
---|---|---|
|
| The max amount of assets depositable to this IonPool. |
getSupportedMarkets
Returns the array representation of the supportedMarkets
set.
Returns
Name | Type | Description |
---|---|---|
|
| Array of supported IonPools. |
containsSupportedMarket
Returns whether the market is part of the supportedMarkets
set.
Parameters
Name | Type | Description |
---|---|---|
|
| The address of the IonPool to be checked. |
Returns
Name | Type | Description |
---|---|---|
|
| The pool is supported if true. If not, false. |
supportedMarketsAt
Returns the element in the array representation of supportedMarkets
. index
must be strictly less than the length of the array.
Parameters
Name | Type | Description |
---|---|---|
|
| The index to be queried on the |
Returns
Name | Type | Description |
---|---|---|
|
| Address at the index of |
supportedMarketsIndexOf
Returns the index of the specified market in the array representation of supportedMarkets
.
The _positions
mapping inside the EnumerableSet.Set
returns the index of the element in the _values
array plus 1. The _positions
value of 0 means that the value is not in the set. If the value is not in the set, this call will revert. Otherwise, it will return the position - 1
value to return the index of the element in the array.
Parameters
Name | Type | Description |
---|---|---|
|
| The address of the IonPool to be queried. |
Returns
Name | Type | Description |
---|---|---|
|
| The index of the pool's location in the array. The return value will always be greater than zero as this function would revert if the market is not part of the set. |
supportedMarketsLength
Length of the array representation of supportedMarkets
.
Returns
Name | Type | Description |
---|---|---|
|
| The length of the |