VaultCore
Inherits: IVaultCoreRecovery
Title: VaultCore
Author: Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC4626.sol)
Diamond facet extending ERC-4626 with strategy hooks for yield aggregation.
All logic lives in VaultCoreLib / ERC4626Lib. This contract is a pure delegator. It owns ONLY its own
selectors — the strategy surface (strategyManager/idleAssets/allocatedAssets/setStrategyManager/
allocateToStrategy/recallFromStrategy), the manager-swap latch (managerSwapLatched/
clearManagerSwapLatch), plus the selectors it REPLACES on the base ERC4626
(totalAssets to include strategy allocations, deposit/mint/withdraw/redeem behind the
read-only-reentrancy guard, and maxDeposit/maxMint to honor the deposit latch, delegating the vault
math to ERC4626Lib directly). It does NOT inherit the ERC4626 facet — doing so would re-export the
ERC-4626 + ERC-20 surfaces and collide with those standalone facets in a Diamond; DeployVaultCore
composes ERC20 + ERC4626 + VaultCore over one shared storage layout.
Initialization order in the consumer's Diamond initializer:
- AccessControlLib.__AccessControl_init(admin)
- ERC20Lib.__ERC20_init(name, symbol)
- ERC4626Lib.__ERC4626_init(asset, decimalsOffset)
- VaultCoreLib.__VaultCore_init()
totalAssets() is overridden to include assets held by registered strategies. ERC4626Lib prices
shares by self-staticcalling the diamond's totalAssets() selector, so the ERC4626 converters,
previews and the mutators here all price on this full NAV. Exits stay capped at idle assets
(maxWithdraw/maxRedeem). If the strategy manager's NAV read fails, totalAssets() reverts and
the vault fails closed until the failing strategy is removed (or the manager replaced; see
IVaultCore.VaultCoreStrategyNavUnavailable). That force removal latches deposits closed on the
manager: deposit/mint revert with IVaultCore.VaultCoreDepositsLatched and maxDeposit/maxMint
return 0 until the manager admin calls clearDepositLatch, while exits reopen capped at idle (#270).
setStrategyManager latches deposits on the vault itself when the swap may strand funds: the old manager
is latched, still reports allocations, or cannot answer. Deposits then stay closed on the new manager
until the vault admin calls clearManagerSwapLatch (#305; IVaultCoreRecovery, a separate interface so
IVaultCore's ERC-165 id is unchanged).
Hook model (D25, #234): the four mutators mint and burn shares through ERC20Lib directly, so they skip
ERC20Pausable's pause, ERC20Votes' checkpoints and ERC20Capped's cap; VaultCore is mutually exclusive with
those extensions. DeployGovernedVault routes the mutators to GovernedVault, which moves voting units.
The vault math is ERC4626Lib's, which lists every difference from OpenZeppelin.
Notes:
- lattice-version: 0.1.0
- lattice-source: OpenZeppelin v5.6.1
Functions
totalAssets
Returns total assets including strategy allocations.
Replaces the base ERC4626 totalAssets() to include assets held by registered strategies.
Reverts with IVaultCore.VaultCoreStrategyNavUnavailable if the strategy manager's read fails.
function totalAssets() public view virtual returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
strategyManager
Returns the strategy manager authorized to allocate/recall vault assets.
function strategyManager() external view virtual returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
idleAssets
Returns assets held idle in the vault (not allocated to any strategy).
function idleAssets() external view virtual returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
allocatedAssets
Returns assets currently allocated to registered strategies.
function allocatedAssets() external view virtual returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
managerSwapLatched
Returns true while a strategy-manager swap keeps the vault's deposits closed.
Consumed by maxDeposit/maxMint and the deposit/mint entry points, which also honor the configured
manager's own latch.
function managerSwapLatched() external view virtual override returns (bool);Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
maxDeposit
Returns the maximum depositable assets for receiver: 0 while deposits are latched closed or the
NAV is unreadable, unbounded otherwise.
Replaces the base ERC4626 maxDeposit to honor the deposit latches (the strategy manager's and the
vault's manager-swap latch).
function maxDeposit(address receiver) public view virtual returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| receiver | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
maxMint
Returns the maximum mintable shares for receiver: 0 while deposits are latched closed or the
NAV is unreadable, unbounded otherwise.
Replaces the base ERC4626 maxMint to honor the deposit latches (the strategy manager's and the
vault's manager-swap latch).
function maxMint(address receiver) public view virtual returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| receiver | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
setStrategyManager
Sets the strategy manager address (admin-gated). Latches deposits on the vault when the swap may strand funds (see IVaultCoreRecovery).
function setStrategyManager(address manager) external virtual;Parameters
| Name | Type | Description |
|---|---|---|
| manager | address |
clearManagerSwapLatch
Clears the manager-swap latch. Admin-only (DEFAULT_ADMIN_ROLE, the role that gates
setStrategyManager).
Clear it once the old manager's stranded funds are back in the vault or written off: deposits then price on a NAV that no longer moves when those funds return. Deposits stay closed while the configured manager's own latch is set. Reverts with VaultCoreManagerSwapLatchNotSet if the latch is not set.
function clearManagerSwapLatch() external virtual override;allocateToStrategy
Pushes amount of idle assets to strategy (strategy-manager-gated).
function allocateToStrategy(address strategy, uint256 amount) external virtual;Parameters
| Name | Type | Description |
|---|---|---|
| strategy | address | |
| amount | uint256 |
recallFromStrategy
Recalls amount of assets from strategy back to the vault (strategy-manager-gated).
function recallFromStrategy(address strategy, uint256 amount) external virtual;Parameters
| Name | Type | Description |
|---|---|---|
| strategy | address | |
| amount | uint256 |
deposit
Deposits assets for shares to receiver (rejected mid-rebalance and while deposits are latched).
function deposit(uint256 assets, address receiver) public virtual returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| assets | uint256 | |
| receiver | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
mint
Mints exactly shares to receiver (rejected mid-rebalance and while deposits are latched).
function mint(uint256 shares, address receiver) public virtual returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| shares | uint256 | |
| receiver | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
withdraw
Withdraws exactly assets to receiver, burning owner's shares (rejected mid-rebalance).
function withdraw(uint256 assets, address receiver, address owner) public virtual returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| assets | uint256 | |
| receiver | address | |
| owner | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
redeem
Redeems exactly shares from owner to receiver (rejected mid-rebalance).
function redeem(uint256 shares, address receiver, address owner) public virtual returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| shares | uint256 | |
| receiver | address | |
| owner | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
exportSelectors
ERC-8153 selector export: this facet's cuttable selectors, tightly packed (4 bytes each).
Excludes exportSelectors() itself (0x0ef22643) - it is never cut into a diamond. Order matches
forge inspect VaultCore methodIdentifiers (alphabetical by signature); kept in exact parity by
ExportSelectorsParityTest. Chunks:
allocateToStrategy(address,uint256) 0x5915e15d
allocatedAssets() 0x36cd2b11
clearManagerSwapLatch() 0x5663a2af
deposit(uint256,address) 0x6e553f65
idleAssets() 0xe16b03a3
managerSwapLatched() 0x5030217b
maxDeposit(address) 0x402d267d
maxMint(address) 0xc63d75b6
mint(uint256,address) 0x94bf804d
recallFromStrategy(address,uint256) 0x43ff28f3
redeem(uint256,address,address) 0xba087652
setStrategyManager(address) 0x5c966646
strategyManager() 0x39b70e38
totalAssets() 0x01e1d114
withdraw(uint256,address,address) 0xb460af94
function exportSelectors() external pure virtual returns (bytes memory selectors);Returns
| Name | Type | Description |
|---|---|---|
| selectors | bytes |