A multi-strategy ERC-4626 yield vault for USDC, written in Vyper 0.4.x and built with Moccasin + snekmate. Inspired by Yearn V3, with a smart strategy router and senior/junior tranching on top.
Status: complete portfolio implementation. 112+ tests passing, plus a Hypothesis stateful fuzzer that already caught and fixed one ERC-4626 rounding edge case during
withdraw. Not audited — see docs/SECURITY.md.
┌────────────────────────────┐
user USDC ──▶│ MultiStrategyVault.vy │──── ERC-4626 shares ───▶ user
│ (ERC-4626 + permit) │
│ liquid buffer + router │
└─────────────┬──────────────┘
│ deposit / withdraw
┌───────────────┼───────────────┐
▼ ▼ ▼
AaveV3Strategy CompoundV3Strategy MorphoStrategy
(aToken) (Comet + COMP) (Morpho Blue)
│ │ │
└─── report() / harvest() ──────┘
│
▼
┌──────────────┐
│ Accountant.vy│ mgmt + perf fees, HWM
└──────────────┘
Optional product layer:
┌────────────────────────────┐
│ TranchedVault.vy │
│ senior (fixed APR) / │
│ junior (first-loss) │
└────────────────────────────┘
| Path | Purpose |
|---|---|
src/ |
Vyper sources (MultiStrategyVault.vy, strategies, etc.) |
tests/ |
pytest + boa unit, fork, and stateful fuzz tests |
script/ |
Moccasin deployment / verification scripts |
lib/ |
Installed dependencies (snekmate) |
moccasin.toml |
Networks, dependencies, test runner |
docs/ |
ARCHITECTURE.md, SECURITY.md |
# 1. Clone & enter
git clone <this-repo> && cd khomdev_keep
# 2. Install Moccasin (one-time, system-wide)
pipx install moccasin # or `uv tool install moccasin`
# 3. Install Vyper / snekmate dependencies
mox install
# 4. Configure environment
cp .env.example .env # then edit RPC URLs + Etherscan key
# 5. (For deployments) register an encrypted keystore
mox wallet import khomdev-keep-deployermox test # unit tests on pyevm
mox test --network mainnet-fork # forked integration tests
mox test -k tranche # filter by name# Sepolia
mox run deploy_vault --network sepolia
mox run deploy_strategies --network sepolia
mox run deploy_tranches --network sepolia
mox run verify --network sepolia- docs/ARCHITECTURE.md — multi-strategy + tranching design
- docs/SECURITY.md — trust model and known risks
- Project scaffolding + dependencies (
mox+ snekmate via PyPI) -
MultiStrategyVault.vy— ERC-4626 + EIP-2612 permit + access-control + pausable,DECIMALS_OFFSET=6virtual shares, smart-routing flag, withdrawal queue, force-removable strategies -
IStrategy.vyiinterface -
AaveV3Strategy.vy— supplies aTokens, no-op harvest (auto-rebase) -
CompoundV3Strategy.vy— Comet supply + COMP claim → Uniswap V3 swap → re-supply, with admin-setmin_out_rate+ 10% slippage cap -
MorphoStrategy.vy— single-market Morpho Blue supplier with compile-time market-id derivation -
Accountant.vy— HWM perf fee + mgmt fee, per-vault state, capped 2% mgmt / 20% perf, plumbed intovault.report()via fee-share dilution -
TranchedVault.vy+Tranche.vy— senior fixed-APR / junior first-loss with maturity, early-redemption penalty, both tranches ERC-4626 with permit - Deployment scripts (
deploy_vault,deploy_strategies,deploy_tranches,verify) - Hypothesis stateful fuzzer — runs randomly-permuted
deposit/withdraw/yield/loss/rebalance/pause sequences against four
vault-wide invariants. Already caught one ERC-4626 rounding bug in
_do_withdraw's strategy-drain path; fixed by switching toredeem(balanceOf)when fully draining a strategy. - docs/ARCHITECTURE.md, docs/SECURITY.md
- Mainnet-fork integration tests (real Aave / Compound / Morpho)
- Sepolia deployment + Etherscan verification
- Add a deposit-limit ratio so senior tranche capacity is throttled relative to junior principal (the "loss cap" promise)
- Replace strategy
set_apr_bpswith an APR oracle (Chainlink or TWAP) - Audit
MIT (TBD before mainnet).