Skip to main content

YDS: Architecture

Purpose: Explain the three-layer YDS architecture, how components interact, the delegatecall pattern, and the design invariants that guide YDS authoring.

Audience: Solidity developers with DeFi knowledge who understand YDS concepts and are ready to learn the system architecture before implementing.

Level: Intermediate

Source of truth: Octant v2 codebase—BaseStrategy, TokenizedStrategy, and MultistrategyVault implementations.

Use this page when: You need to understand how YDS components fit together; you want to know what BaseStrategy and TokenizedStrategy do; you're designing a new YDS strategy; you need to explain architecture to team members.

Do not use this page for: Step-by-step lifecycle details; specific hook implementation patterns; practical coding examples; operational workflows (see Mental Model & Lifecycle and Writing a YDS Strategy instead).

Before you read this page
TL;DR

YDS reuses Yearn V3’s ERC-4626 design, but changes where profit goes. A YDS is a single-strategy ERC-4626 vault. Instead of compounding profit to depositors, net profit is represented as donation shares minted to a configured donation address. If burning is enabled, losses burn donation shares first up to the available buffer. Your strategy inherits a thin BaseStrategy, overrides three core hooks, and delegates the standardized vault machinery to a shared TokenizedStrategy implementation.

Overview

This page explains the architecture of a Yield Donating Strategy from the point of view of an external DeFi engineer.

The first distinction to keep clear is this:

  • a YDS strategy vault is itself an ERC-4626 deposit surface,
  • a MultistrategyVault is a separate allocator vault that can sit above one or more strategy vaults.

If you are authoring a YDS, you are normally building the first of those two layers.

What YDS inherits from the shared Octant model

YDS keeps several important properties from the shared Octant strategy framework:

  • ERC-4626 deposits and withdrawals
  • shared accounting and role gating through TokenizedStrategy
  • donation-share minting and loss-buffer settlement at report()
  • first-deposit minimum-liquidity seeding in the shared YDS implementation
  • permissionless composition under multistrategy vaults when needed

That means the strategy author does not rebuild vault accounting or access control from scratch.

What YDS changes versus a normal yield vault

In a normal ERC-4626 yield vault, profit increases depositor value. In YDS, realized profit is redirected to the donation address instead:

  • profit is measured during report(),
  • new shares are minted to the donation address,
  • depositor PPS does not rise from that profit,
  • losses burn donation shares first when the buffer exists and burning is enabled.

On the first successful deposit or mint into an empty YDS, the shared implementation permanently locks 1_000 shares at address(0xdead). That protects the initial share ratio from dust-style edge cases. It also means the first depositor receives assets - 1000 shares, not an exact 1:1 share amount.

This is the core architectural change.

Components and layers

1. Strategy vault layer

The strategy vault is the contract you author when building a standalone YDS.

It:

  • accepts one underlying asset,
  • exposes the ERC-4626 deposit and withdrawal surface,
  • integrates one external yield source,
  • measures profit and loss,
  • settles donation shares during report().

In the common authoring path, your concrete contract inherits BaseStrategy and keeps only strategy-specific state and logic.

2. Shared implementation layer

Concrete strategies delegate the standardized ERC-4626 mechanics, accounting, and role gating to the shared TokenizedStrategy implementation.

That keeps strategist code small, reuses hardened shared logic, and preserves the Yearn-style pattern of cheap, permissionless deployment of single-asset ERC-4626 strategy vaults.

3. Optional multistrategy vault layer

If your deployment wants one deposit surface across several strategies, a separate allocator vault can sit above them.

In octant-v2-core, that role is served by MultistrategyVault or MultistrategyLockedVault.

That vault layer:

  • accepts user deposits,
  • allocates debt across attached strategies,
  • manages queue policy and rebalancing,
  • separately books strategy-level P&L into vault accounting.

This layer is optional from the strategist’s point of view.

The following diagram shows the three-layer architecture and how they interact:

The donation address can be an EOA, Safe, splitter, or forwarder, but it is still the address that receives and, when burn protection is enabled, may later burn strategy shares.

What delegatecall means here

Your strategy contract holds the state (balances, approvals, configuration). The shared TokenizedStrategy contract holds the logic (deposit, withdraw, report, share accounting). When a user interacts with your strategy address, delegatecall makes TokenizedStrategy's code run using your strategy's storage. → Full explanation

The YDS authoring surface

At the BaseStrategy layer, the three core strategy hooks are:

  • _deployFunds
  • _freeFunds
  • _harvestAndReport

These hooks define the strategy-specific behavior. The rest of the lifecycle is handled by the shared strategy implementation.

Data flow

Standalone strategy vault

User -> YDS strategy vault -> external yield source -> report() -> donation shares minted to donation address

Multistrategy composition

User -> MultistrategyVault -> allocates capital -> YDS strategy vault(s) -> report() -> donation shares minted at strategy layer

The second flow does not turn the YDS into a non-vault component. It only adds a vault layer above it.

Design invariants to internalize

  • A YDS is itself a vault. It is not just a helper module behind some other canonical vault.
  • One strategy vault, one primary yield logic path. The standalone YDS handles one asset and one strategy integration surface.
  • Donation happens at report. Profit becomes donation shares only when accounting is finalized.
  • The first YDS deposit seeds minimum liquidity. Empty yield-donating strategies lock 1_000 shares at address(0xdead); test and preview expectations need to account for this.
  • Loss protection is conditional. Burning donation shares helps only when it is enabled and the available donation-share buffer is large enough.
  • Disable burning through a report when needed. In 1.2.0-develop.15, disabling burn protection from an enabled state can revert with report before disabling burning while pending dragon shares exist; use reportAndDisableBurning() for the atomic operator path.
  • Multistrategy composition is separate. Allocation across strategies belongs to MultistrategyVault, not to the standalone YDS contract.

Key takeaway

Think in layers.

When you build YDS, you are usually building a strategy vault. When you need one vault above several strategies, you add a multistrategy vault. “Funding vault” is a useful umbrella phrase for the product pattern, but the concrete deployable surfaces are the strategy vault and the multistrategy vault.