Build a vault that allows users to deposit ERC20 tokens, safely withdraw their principal, and generate yield through a real protocol integration Aave.
All yield should be trackable and fully extractable by an admin or designated role.
This project takes reference and inspiration from Aave's ATokenVault for the core vault functionality, while extending it with multi-asset support and custom yield distribution features.
This project implements a Multi-Token Vault that integrates with Aave V3 to provide yield generation across multiple ERC20 tokens. The vault supports both custom yield distribution using Chainlink VRF and multi-asset management with a unified interface.
Project Overview: Loom Demo Video
- Deposit/Withdraw: Users can deposit and withdraw at any time
- Principal Protection: Principal is always withdrawable (1:1 ratio maintained)
- Yield Accumulation: Yield generated from Aave remains in vault until harvested
- Admin Control: Only admin can harvest accumulated yield
- Protocol: Integrated with Aave V3 on Ethereum Mainnet
- Tested Assets: DAI and USDC
- Yield Generation: Real yield accrual through aToken balances
- Testing: Demonstrated on mainnet fork environment
- Random Selection: Uses Chainlink VRF for fair winner selection
- Configurable: Admin can set yield amount and winner count
- Transparency: All requests and distributions are trackable
- Unified Interface: Single vault for multiple ERC20 tokens
- Configurable: Admin can add/remove supported assets
- Cross-Asset Withdrawals: Users can withdraw in any supported token
- MockDEX Integration: Custom DEX for seamless asset swapping
- Unified Share System: Common shares calculated based on USD value
- Purpose: Created a custom MockDEX to enable depositors to withdraw any supported asset
- Functionality: Handles DAI ↔ USDC swaps with 1:1 exchange rate
- Integration: Automatically triggered when vault lacks sufficient requested asset
- Benefits: Users can deposit DAI but withdraw USDC (or vice versa)
- Common Shares: All depositors receive the same share token (MTV) regardless of deposit asset
- USD-Based Calculation: Share value calculated using USD price oracle
- Proportional Ownership: Each share represents proportional ownership of total vault value
- Cross-Asset Value: Share value reflects combined value of all supported assets
- MultiTokenVault.sol - Main vault contract with ERC4626 compliance and VRF integration
- MultiTokenVaultStorage.sol - Storage layout for upgradeability and state management
- MockDEX.sol - Mock DEX for cross-asset swaps and testing
- Purpose: Main vault implementation with multi-asset support
- Features:
- ERC4626 standard compliance
- Aave V3 integration for yield generation
- Chainlink VRF for random yield distribution
- Cross-asset deposit/withdrawal functionality
- Admin controls for yield harvesting
- Purpose: Storage layout for upgradeable vault
- Features:
- Multi-asset mappings and arrays
- Fee management per asset
- USD value tracking
- VRF state variables
- MockDEX integration
- Purpose: Custom mock decentralized exchange for DAI/USDC swaps
- Features:
- DAI/USDC swap functionality (primary use case)
- Configurable exchange rates (1:1 default)
- Quote and swap functions
- Event logging for transactions
- Decimal handling (DAI: 18 decimals, USDC: 6 decimals)
- ERC4626 Compliance: Standard vault interface
- Aave V3 Integration: Real yield generation through aToken balances
- VRF Integration: Built-in Chainlink VRF for fair random yield distribution
- Multi-Asset Support: Unified interface for multiple ERC20 tokens
- Admin Controls: Secure yield harvesting and asset management
- Cross-Asset Swaps: Flexible withdrawal options via MockDEX
- Deposits: Multi-asset deposit functionality (DAI/USDC tested)
- Withdrawals: Direct and cross-asset withdrawals (DAI↔USDC swaps)
- Yield Accrual: Real yield generation through Aave
- Admin Harvest: Yield extraction by admin
- VRF Integration: Random yield distribution with mocked randomness
- MockDEX Testing: DAI/USDC swap functionality
- Edge Cases: Swap failures, insufficient liquidity
- Math Verification: Correct yield distribution
- Mocked Randomness: For testing purposes, random numbers are mocked to ensure deterministic test results
- Simulation: Tests simulate the VRF callback process without requiring actual Chainlink VRF requests
- Algorithm Verification: Winner selection algorithm is tested with known random seeds
- Production Ready: In production, real Chainlink VRF provides cryptographically secure randomness
# Run all tests
forge test
# Run specific test
forge test --match-test testSwapBasedWithdrawals
# Run on mainnet fork
forge test --fork-url https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY// User deposits 1000 DAI
vault.depositMulti(DAI, 1000e18, user);
// Vault automatically:
// 1. Transfers DAI from user to vault
// 2. Supplies DAI to Aave V3 Pool
// 3. Receives aDAI tokens in return
// 4. Mints MTV shares to user based on USD value- aToken Balance Growth: aDAI balance increases over time due to Aave's lending yield
- Real Yield: Not simulated - actual interest earned from Aave's lending pool
- Automatic Compounding: Yield is automatically reinvested in the aToken
- Transparent Tracking: Vault tracks aToken balance changes to measure yield
// Yield = Current aToken Balance - Last Recorded Balance
uint256 newYield = currentATokenBalance - _lastVaultBalance[asset];
// Example:
// Initial: 1000 aDAI
// After 1 day: 1000.1 aDAI (0.1 DAI yield)
// Yield = 1000.1 - 1000 = 0.1 DAIOption A: Admin Harvest
- Admin calls
harvestYield(asset)to extract accumulated yield - Yield is withdrawn from Aave and sent to admin
- Vault's aToken balance decreases by yield amount
Option B: VRF Random Distribution
- Admin calls
requestRandomYieldDistribution() - Chainlink VRF selects random winners from participants
- Yield is distributed directly to winners' addresses
- Creates a lottery system for yield distribution
- User Deposit: User deposits ERC20 tokens (DAI/USDC)
- Aave Supply: Vault supplies tokens to Aave V3 lending pool
- aToken Receipt: Vault receives aTokens (aDAI/aUSDC) representing deposit + yield
- Yield Accrual: aToken balance increases over time due to Aave's lending interest
- Yield Tracking: Vault monitors aToken balance changes to calculate yield
- Yield Distribution: Admin can harvest or distribute yield via VRF lottery
- Reason: Most established lending protocol with high TVL
- Benefits: Real yield generation, battle-tested security
- Integration: Direct aToken balance tracking
- Reason: Unified interface for better UX
- Benefits: Single vault for multiple tokens, cross-asset withdrawals
- Implementation: ERC4626 standard with asset mapping
- Yield Rates: Aave lending rates remain positive and sustainable
- Liquidity: MockDEX maintains sufficient liquidity for cross-asset swaps
- Price Stability: USD prices remain relatively stable during vault operations
- MockDEX Exchange Rate: Assumed 1:1 exchange rate between DAI and USDC for testing purposes
- Yield Simulation:
simulateYieldfunction used for testing to demonstrate 1:1 yield accrual without waiting for real Aave yield - User Behavior: Users understand the unified share system and cross-asset withdrawals
- Admin Trust: Vault admin acts in good faith for yield harvesting and distribution
- Unified Shares: Chose single share token (MTV) for simplicity and cross-asset compatibility
- USD Pricing: Used USD as base currency for share calculations to handle multiple assets
- MockDEX: Created custom DEX for testing rather than integrating with real DEX (Uniswap)
- 1:1 Exchange Rate: Simplified MockDEX with 1:1 DAI/USDC rate for testing simplicity
- VRF Integration: Implemented VRF for fair random distribution rather than deterministic rules
- Aave Integration: Chose Aave over other protocols for its maturity and security track record
-
Clone Repository
git clone https://github.com/atkosX/aave-vault.git cd aave-vault -
Install Dependencies
forge install
-
Run Tests
forge test -
Deploy to Fork
anvil --fork-url https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY forge script script/DeployMultiTokenVault.s.sol --rpc-url http://localhost:8545 --broadcast