Stable Vaults is a semi-fixed rate vault protocol developed by Aave Labs. It allows users to deposit assets into "SubVaults" that offer a specific per-second interest rate, enabling predictable yield generation. Deposited funds are allocated to yield-generating strategies (e.g. Aave). The system tracks each user's original principal independently from accrued interest. In the event the vault cannot meet its total interest obligations, users are prioritized to withdraw at least their original deposit amount.
The protocol utilizes a modular architecture and cross-chain capabilities, separating accounting logic from earning logic.
- Stable Vaults
The core component is the StableVault, which manages user positions, sub-vaults, and interest accrual.
- SubVaults: Virtual vaults with a defined
perSecondRate(interest rate). This rate determines the yield users in a given SubVault earn, effectively translating to an APY number (e.g., a higher rate per second results in a higher APY). - User Positions: Users hold shares in a specific SubVault.
- IOU Tokens: Used during the withdrawal process to represent a claim on assets. An IOU token unit represents a unit of the common denomination asset (e.g. USD). IOUs can be exchanged for any asset supported by the system on the chain which the IOUs are being exchanged.
Funds deposited into the protocol are managed by Allocator contracts (one Allocator is deployed to each of the Accounting Chain and Earning Chains), which deploy assets into yield-generating strategies.
- Allocator: Holds idle funds and deposits them into whitelisted strategies which act as ERC-4626 compliant adapters to underlying yield-generating protocols.
- Rebalancing: Managers can call
rebalance()on the Allocator to move funds between strategies or swap assets to optimize yield. Swaps are enforced to be 1:1 where aslippage coverage sourcemust make up the difference for slippage and/or fees.
The protocol operates on a model where the Accounting Chain is the primary command center and Earning Chains act as sources of yield. Contracts on the Earning Chain can only bridge funds back to their canonical Accounting Chain.
- Accounting Chain: Hosts the
StableVault,FundsHandlerandAllocatorfor local yield strategies. It tracks the global state of user deposits and total system liquidity. - Earning Chains: Host
EarningChainGatewayand localAllocators. Funds are bridged here to access yield opportunities not available on the Accounting Chain. - Bridge adapters: Cross-chain messages and funds move through bridge adapters. The repository currently includes Chainlink CCIP and a.DI adapters.
- Price oracles (both chains):
PriceOracleis the canonical price entry point for protocol contracts.- Asset-specific adapters (e.g.
ChainlinkPriceOracleAdapter) are registered onPriceOracle. validatePriceenforces staleness and minimum-valid-price checks for safety-critical flows (e.g. deposits).getPriceis used for aggregation and returns0for stale prices; prices above1 RAYare capped to1 RAY.
- Chain balance oracle (Accounting Chain):
FundsHandlerandAccountingChainGatewayread fromChainBalanceOracle.ChainBalanceOracledelegates per-chain reads to registered adapters.ChainlinkChainBalanceOracleAdapterdecodes snapshots published fromEarningChainStateProviderand marks data stale using heartbeat + buffer.AccountingChainGatewayvalidates inboundRETURN_FUNDSandBURN_IOU_TOKENmessages using source chain block numbers (message block number must be<= sourceChainBlockNumberfrom the latest snapshot).
- Snapshot source:
EarningChainStateProvider.getState()encodes the Earning Chain balance snapshot (balanceRay, source timestamp, source block number).- This snapshot is published by the Chainlink network to a bundle feed consumed by
ChainlinkChainBalanceOracleAdapter.
- Bridging Funds:
- Managers call
pushFundsToChainon theFundsHandler. This bridges assets via theAccountingChainGatewayto an Earning Chain. - Managers call
pushFundsToAccountingChainon theEarningChainGatewayto return funds to the Accounting Chain.
- Managers call
- Strategy Management:
- Managers add, remove, trust, distrust, and order strategies on the
Allocatorto direct funds into the most efficient yield sources.
- Managers add, remove, trust, distrust, and order strategies on the
Users can deposit supported assets into the vault (supported assets are managed on the AssetRegistry contract).
- Call
deposit: The user calls thedeposit(address user, address asset, uint256 amount, bytes calldata policyData)function on theStableVaultcontract. - Share Calculation: The deposited amount is converted into shares of a SubVault based on the current conversion rate.
- Position Update: The user's position is credited with the calculated shares.
Withdrawals are a two-step process designed to ensure liquidity management and proper accounting.
-
Request Withdrawal:
- The user calls
requestWithdrawal(address user, uint256 requestedAmountInRay, bytes calldata policyData). - A corresponding amount of the user's shares are burned.
- IOU Tokens are minted to the user, representing their claim on the underlying assets.
- This action must be performed on the Accounting Chain since the
StableVaultis the source of truth for a user's claimable balance.
- The user calls
-
Bridging IOUs
- IOUs can be bridged between chains using the
IouTokenManager.bridgeTokens(...)function. - If bridging from the Accounting Chain to an Earning Chain, IOUs are locked in the
IouTokenManageron the source chain, and an equivalent amount is minted on the destination chain. - If bridging from an Earning Chain to the Accounting Chain, IOUs are burned on the source chain, and released from the
IouTokenManageron the destination chain. IOUs can also be bridged from one Earning Chain to another. - This allows users to move their claim on assets to the chain where they wish to withdraw or utilize the IOUs. The reason for this design is to allow users to withdraw even if managers are offline and do not repatriate funds back to the Accounting Chain.
- Bridge fee approvals: The bridge fee is paid by the caller (
msg.sender). When the fee is paid in an ERC-20 token, the caller must approve the specificbridgeAdapterpassed in the call to pull the fee. The adapter pulls the quoted fee with no per-transaction cap, so callers should limit the approval to the expected fee amount rather than granting an unlimited allowance. This bounds the worst case if a bridge fee quoter ever returns an over-stated fee. Native-token fees are bounded by themsg.valuesent and require no approval.
- IOUs can be bridged between chains using the
-
Execute Withdrawal: IOUs can be exchanged for assets on either the Accounting Chain or Earning Chains.
-
Accounting Chain:
- Contract:
StableVault - Function:
executeWithdrawal(...) - Process: IOUs are burned via
IouTokenManager. TheWithdrawalExecutionPolicyenforces the protocol's policies and operational costs associated with the withdrawal. Assets are withdrawn from the localAllocatorthen transferred to the user from theTransferHelper.
- Contract:
-
Earning Chains:
- Contract:
EarningChainGateway - Function:
exchangeIouTokens(...) - Process: IOUs are burned locally. The
WithdrawalExecutionPolicyenforces the protocol's policies and operational costs associated with the withdrawal. Assets are withdrawn from the localAllocator. A cross-chain message is sent to the Accounting Chain to burn the corresponding locked IOUs. Assets are transferred to the user from theTransferHelper. - Bridge fee approvals: This call sends a cross-chain message, so the same fee-approval guidance as Bridging IOUs applies. The caller (
msg.sender) pays the bridge fee; when it is paid in an ERC-20 token, approve the specificbridgeAdapterpassed in the call and limit the approval to the expected fee amount rather than granting an unlimited allowance. Native-token fees are bounded by themsg.valuesent and require no approval.
- Contract:
-
stable-vault/
├── src/ # Main source code
│ ├── bridging/ # Adapters used by protocol to interface with cross-chain bridges
│ │ ├── adi/ # a.DI adapter logic
│ │ └── ccip/ # Chainlink CCIP adapter logic
│ ├── core/ # Core protocol logic
│ │ ├── accounting/ # Accounting chain logic (Vault, FundsHandler)
│ │ ├── earning/ # Earning chain logic
│ │ └── ious/ # IOU token management
│ ├── interfaces/ # Protocol interfaces
│ ├── libraries/ # Shared libraries (Math, Assets, etc.)
│ ├── misc/ # Miscellaneous utils (contracts inherited by core/periphery contracts)
│ ├── oracles/ # Price and chain balance oracle contracts and adapters
│ │ ├── balance/ # Chain balance oracle and adapters
│ │ ├── common/ # Shared oracle logic
│ │ └── price/ # Price oracle and adapters
│ ├── periphery/ # Peripheral contracts (registries, swapper, coverage vault, etc.)
│ ├── policies/ # Deposit, withdrawal-execution, and funds-bridging policies
│ │ └── base/ # Shared policy base contracts
│ └── types/ # Shared constants and errors
├── config/ # Deployment configuration per environment
├── deployments/ # Deployment address artifacts per environment
├── audits/ # Security audit reports
├── tools/ # Auxiliary tooling
├── test/ # Test suite
├── script/ # Deployment, upgrade, setup, and interaction scripts
└── lib/ # Foundry dependencies
- Foundry - Development framework
curl -L https://foundry.paradigm.xyz | bash foundryup # Update to latest version
Dependencies are managed via git submodules in the lib directory.
forge buildforge test- Run specific test:
forge test --match-contract ContractName - Run with verbosity:
forge test -vvv
Gas-cost regression checks live under test/gas/. They run on every PR via the gas-diff CI job, which compares the new measurements against a baseline uploaded from the latest master build and posts a sticky PR comment with the diff. Generated snapshot files (snapshots/) are gitignored — the baseline lives only as a CI artifact.
To preview the same numbers locally, use the gas profile (which enables isolate = true for accurate per-call measurement):
FOUNDRY_PROFILE=gas forge testGenerated files in snapshots/:
StableVault.Operations.json— user-facing StableVault interactionsBurnIouToken.json— CCIPBURN_IOU_TOKENmessage processing (used to size the minimum CCIPgasLimit)
forge fmtThe protocol has been audited by multiple security firms. Reports are available under the audits/ directory:
- Certora
- ChainSecurity
- J. Feist
Further details will be made available soon.
Stable Vaults software is under a proprietary license (All Rights Reserved © Aave Labs), see LICENSE. Each Solidity file declares its applicable license.