Skip to main content

DeFi Concepts You'll Need

tip

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:

  1. Deposit 100 DAI → you receive 100 vault shares
  2. Vault earns yield over time
  3. 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

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:

  1. Profit is measured during report()
  2. New shares are minted and sent to the donation address (not to you)
  3. Your PPS stays flat at 1.00 during normal profit cycles
  4. 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


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 BaseStrategy contract stays small (just strategy-specific logic)
  • A shared TokenizedStrategy handles 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:

  1. User calls deposit(100 DAI) on Strategy contract (your thin wrapper)
  2. Strategy doesn't have a deposit() function, so it hits the fallback
  3. Fallback delegatecalls TokenizedStrategy.deposit()
  4. TokenizedStrategy runs deposit logic using Strategy's storage
  5. Shares get minted to the user's address in Strategy's storage
  6. User now owns shares of your specific strategy

Mermaid sequence diagram

Where you'll see delegatecall in these docs


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:

  1. Measures how much profit or loss the strategy made since the last report
  2. Calculates how many donation shares to mint or burn
  3. 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() and tend()
  • BaseStrategy: onlyKeepers modifier restricts report() 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:

  1. 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.
  2. 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) inherit BaseStrategy, which delegates to a shared TokenizedStrategy implementation
  • Allocation mechanisms delegate to TokenizedAllocationMechanism: All custom allocation rounds inherit BaseAllocationMechanism and 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:

From there, you can jump into building: