Found Academy useful? A $5 donation by May 14 helps us ship more, faster. Every donor counts (QF matching).

Donate

Section 12 of 18

Final Build
+50 Lynx

Single-Strategy Vault MVP

Final Build

Submit your complete protocol and run the full test suite. Earn the "yearn-v2-builder" badge on completion.

Single-Strategy Vault MVP

You have built sections 2 through 11. Vault chain: sections 2-6 and 9-11. Strategy chain: sections 7 (interfaces) and 8 (BaseStrategy). This is a checkpoint: the test for this section verifies that everything integrates correctly. No new code is added here.

What Should Work Now

If you connect a single concrete strategy to the vault you have built, this end-to-end flow runs:

  1. Deploy and initialize. Constructor (or initVault for isolated tests) sets token, name, symbol, and roles. activation is set; lastReport is set.
  2. User deposits. deposit(amount, recipient) mints share tokens to the recipient using the virtual-offset math from section 5. totalIdle increases by amount. The first depositor pays the cost of the virtual offset (negligibly).
  3. Governance adds a strategy. addStrategy(strategyAddr, debtRatio, min, max, perfFee) registers it and appends to the withdrawal queue.
  4. Strategy harvests for the first time. It reads creditAvailable(self) (gets the full min(strategy_DebtLimit, vault_DebtLimit, totalIdle, maxDebtPerHarvest)), pulls that credit by calling report(0, 0, 0) with no gain or loss yet. Vault transfers credit to strategy; strategy.totalDebt increases; vault.totalIdle decreases by the same amount.
  5. Strategy earns yield off-chain. Time passes. Strategy's underlying balance grows beyond its totalDebt.
  6. Strategy reports gain. It calls report(gain, 0, 0). The vault validates the gain against the strategy's actual balance, charges 0 fees (section 16 not yet built), updates strategy.totalGain and strategy.totalDebt += credit for any new credit available, and locks the gain in lockedProfit (naive: full gain, since section 13's decay isn't built yet).
  7. User withdraws. If totalIdle covers the requested value, the vault transfers from idle. (Section 14 adds the queue-iteration path for the case where it doesn't.)

What's Missing

You will add the rest in Part 3:

  • Locked profit degradation (section 13): the just-in-time defense. Without it, a depositor could front-run a harvest and claim the freshly-reported gain. Right now _updateLockedProfit is a naive stub that locks the full gain; once you build the time-decay version, the lock unlocks linearly over ~6 hours.
  • Multi-strategy withdraw (section 14): the user's withdraw call when totalIdle is insufficient. Walks the withdrawalQueue, pulls from each strategy, accounts for losses.
  • Strategy harvest cycle (section 15): the actual harvest() and tend() functions on BaseStrategy's subclass that orchestrate _prepareReturn → vault.report → _adjustPosition.
  • Fees (section 16): management fee accruing on totalDebt, performance fees on gain, fee-as-share-mint mechanism. Right now _assessFees is a stub returning 0.
  • Emergency shutdown and the deployable constructor (section 17): the Vault contract that ships to mainnet, plus the emergency switch that drains every strategy on the next harvest.

How the Test Verifies This

tests/12-vault-mvp-checkpoint.json checks structural integrity:

  • The contract chain is intact: VaultStorage → VaultShareToken → VaultShareMath → VaultDeposit → VaultTotalAssets → VaultAddStrategy → VaultCreditDebt → VaultReport.
  • The key public functions exist with the right signatures: deposit, totalAssets, addStrategy, creditAvailable, debtOutstanding, report.
  • The storage variables that span sections are present: totalIdle, totalDebt, strategies, withdrawalQueue, lockedProfit.
  • The first-depositor defense constants and override are in place.

The test does NOT execute Solidity (the runner is a regex matcher). If you want to verify behavior, deploy the chain to a local Anvil and run a hand-written Foundry test through the seven-step flow above.

Take a Break

Part 3 raises the difficulty. Sections 13 and 14 add the most subtle math in the module (time-decay locking, multi-strategy queue iteration with loss accounting). The MVP you have right now is the design Yearn V1 was, a single-strategy vault with no JIT defense. Part 3 turns it into Yearn V2.

Your Complete Protocol

Solution.sol
Solidity
Loading editor...