DeFi Concepts You'll Need
This page explains DeFi concepts that the rest of the Octant docs assume you know. If you're already comfortable with ERC-4626, delegatecall, and keeper patterns, you can skip this page and go straight to the Developer Orientation.
Purpose: Provide foundational knowledge of DeFi and Solidity patterns that Octant v2 depends on. Audience: Developers new to DeFi, vault standards, or delegatecall patterns. Level: Beginner Source of truth: Ethereum standards, Octant v2 architecture, and smart contract patterns. Use this page when: You encounter ERC-4626, Price Per Share, delegatecall, keepers, or proxy patterns in other parts of the Octant docs and need a refresher. Do not use this page for: Comprehensive Solidity tutorials or deep cryptographic theory (see external resources for those).
ERC-4626: The Vault Standard
What ERC-4626 is
A vault is a smart contract that accepts your tokens, holds them, generates yield, and gives you back shares representing your ownership stake. Think of it like a bank account: you deposit money, the bank invests it, and you own a claim on both your original deposit and any growth.
ERC-4626 is a standardized interface that all vaults implement. When a vault follows ERC-4626, any tool or protocol that understands ERC-4626 can work with it automatically—no custom integration needed.
The basic cycle:
- Deposit 100 DAI → you receive 100 vault shares
- Vault earns yield over time
- Withdraw your 100 shares → vault converts them back to DAI (which is now more than 100 if the vault earned yield)
Why Octant uses it
Composability. If every vault speaks the same language (ERC-4626), then:
- A yield router can send funds to any vault
- An allocation mechanism can receive yield from any vault
- A multistrategy vault can sit above many different strategy vaults
- New tools and integrations plug in without rewriting code
Without standardization, every new vault would require custom wrappers, and adding a new integration would be expensive and fragile.
Where you'll see ERC-4626 in these docs
- Every strategy vault implements ERC-4626 (the
deposit(),withdraw(),balanceOf()interface you know from ERC-20) - Every multistrategy vault implements ERC-4626 on top
- The Yield Donating Strategy section explains how we change what ERC-4626 does with profit
- Code references: TokenizedStrategy, MultistrategyVault
For a detailed ERC-4626 explainer, see the Ethereum.org ERC-4626 docs.
Price Per Share (PPS)
What PPS is
Price per share (often abbreviated PPS) is the exchange rate between vault shares and the underlying asset.
PPS = Total Assets in Vault / Total Shares Outstanding
If a vault holds 1000 DAI and has 1000 shares, PPS = 1.00. If it holds 1050 DAI and still has 1000 shares, PPS = 1.05.
How PPS normally works
In a traditional ERC-4626 vault, when the vault earns yield, PPS goes up. This means your shares become worth more:
- You deposit 100 DAI → receive 100 shares → PPS is 1.00
- Vault earns 5 DAI in yield → now holds 105 DAI
- PPS is now 1.05
- Your 100 shares are now worth 105 DAI
The profit goes directly to you.
How PPS works in Octant
Octant changes the model. Profit does not go to you—it goes to the donation address instead.
When Octant's strategy earns yield:
- Profit is measured during
report() - New shares are minted and sent to the donation address (not to you)
- Your PPS stays flat at 1.00 during normal profit cycles
- Losses work in reverse: if the vault loses value and burning is enabled, donation shares are burned first as a buffer
Numeric example:
- You deposit 100 DAI → receive 100 shares → PPS is 1.00
- Strategy earns 5 DAI → profit is measured
- In a normal vault: PPS rises to 1.05, you're 5 DAI richer
- In Octant: 5 new shares are minted to the donation address, PPS stays 1.00, you keep your 100 shares, and 5 DAI worth of value (the new shares) goes to the donation address
- Total assets = 105 DAI, but total shares now = 105 (100 yours + 5 donation)
- PPS still = 1.00
This is the core design: you keep your principal safe, only the yield leaves for public goods.
Where you'll see PPS in these docs
- YDS Mental Model & Lifecycle walks through PPS changes in detail
- Core Concepts: The report() loop explains when new shares are minted
- Health check configuration controls PPS bounds
Delegatecall: Sharing Code Between Contracts
What delegatecall is
Delegatecall is a special way for one contract to run code from another contract while using its own storage.
Think of it like this: A chef is hired to cook in your kitchen. The chef brings the recipe (code), but uses your pots, pans, and ingredients (storage). The food ends up in your kitchen, not the chef's.
Normally, when contract A calls a function on contract B, contract B's code runs and contract B's storage gets updated. With delegatecall, contract A's code runs contract B's function but updates contract A's storage instead.
Why Octant uses delegatecall
Every strategy vault needs the same ERC-4626 machinery: deposits, withdrawals, share accounting, and donation settlement. Without delegatecall, every strategy would have to copy 2000+ lines of code.
With delegatecall:
- Your
BaseStrategycontract stays small (just strategy-specific logic) - A shared
TokenizedStrategyhandles all the standard vault machinery - When you call
deposit()on your strategy,TokenizedStrategy's code runs, but it updates your strategy's storage - You deploy once, you get ERC-4626 for free, and all strategies share hardened battle-tested code
The practical flow:
- User calls
deposit(100 DAI)on Strategy contract (your thin wrapper) - Strategy doesn't have a
deposit()function, so it hits the fallback - Fallback delegatecalls
TokenizedStrategy.deposit() TokenizedStrategyruns deposit logic using Strategy's storage- Shares get minted to the user's address in Strategy's storage
- User now owns shares of your specific strategy
Mermaid sequence diagram
Where you'll see delegatecall in these docs
- BaseStrategy: your contract; delegates to TokenizedStrategy
- TokenizedStrategy: shared implementation that all strategies delegate to
- Similarly, BaseAllocationMechanism delegates to TokenizedAllocationMechanism
- Important: delegatecall is not an upgradeable proxy. The
TokenizedStrategyaddress is set at construction time and never changes.
Keepers: Automated Contract Callers
What a keeper is
A keeper is an off-chain service or bot that watches for conditions and calls contract functions on a schedule or when triggered. It's like a cron job, but for smart contracts.
The blockchain itself doesn't run code. Someone has to push the button. That someone is a keeper.
Why Octant needs keepers
Every strategy has a report() function that:
- Measures how much profit or loss the strategy made since the last report
- Calculates how many donation shares to mint or burn
- Updates the strategy's accounting
But the blockchain can't call report() by itself. It needs an off-chain agent—a keeper—to call it periodically.
What happens if no one calls report()
- Yield sits dormant in the external yield source (e.g., in Aave)
- Profit is never settled and never turned into donation shares
- The donation address never receives anything
- Users' shares don't reflect the real value earned
- The system stalls
Where you'll see keepers in these docs
- Every strategy has a keeper role that is authorized to call
report()andtend() - BaseStrategy:
onlyKeepersmodifier restrictsreport()to keeper or management - TokenizedStrategy: handles keeper permissions
- Deployment guides explain how to set up keeper infrastructure
Proxy Patterns: Why Contracts Delegate to Shared Implementations
What the proxy pattern is
A proxy pattern solves two problems:
- Code duplication: If you deploy 100 identical ERC-4626 vaults, you deploy 100 copies of the same code. That's gas-wasteful and makes upgrades hard.
- Update friction: If a bug is found, you have to deploy a new version of every vault.
The solution: One thin proxy contract per strategy, one shared implementation contract.
- Proxy (your strategy): thin, stores strategy-specific data, delegates to shared implementation
- Implementation (TokenizedStrategy): holds all the standard ERC-4626 logic
When you call a function, the proxy delegates to the implementation, which runs using the proxy's storage.
Octant's variant
Octant's proxy pattern is not upgradeable. The implementation address is baked in at construction time. This is a safety choice: it prevents the team from swapping in a malicious implementation later.
// WHY: Implementation is immutable—set once, never changed.
address public immutable TOKENIZED_STRATEGY_ADDRESS;
Mermaid diagram
Where you'll see proxy patterns in these docs
- Strategies delegate to
TokenizedStrategy: All strategy vaults (YDS and YSS) inheritBaseStrategy, which delegates to a sharedTokenizedStrategyimplementation - Allocation mechanisms delegate to
TokenizedAllocationMechanism: All custom allocation rounds inheritBaseAllocationMechanismand delegate to shared implementation logic - YDS Architecture: explains the strategy-level proxy pattern
- Core Concepts: allocation mechanisms use the same delegatecall model
You're ready
You now understand the foundational concepts that the rest of the Octant docs build on. The next step is to lock in your mental model:
- Developer Orientation — a guided walkthrough of the core components
- Core Concepts — deeper dive into vaults, strategies, and the report loop
From there, you can jump into building:
- Yield Donating Strategy — build a strategy that donates yield
- Yield Skimming Strategy — build a strategy that captures appreciation
- Allocation Mechanisms — build governance over yield distribution