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

Donate

Section 7 of 18

Build
+10 Lynx

Strategy and Vault Interfaces

What You Are Building

Two interfaces in one file: IStrategy (what the vault calls on a strategy) and IVaultAPI (what a strategy calls on its vault). No contracts, no inheritance chain, section 7 is purely the boundary between two separate inheritance lines.

Compound did the same thing in section 9 with ComptrollerInterface declared up front so the Comptroller and CToken sides could be developed independently. Interface design is a discipline. Get it right here and the rest of Part 2 falls into place.

Why Interfaces First

The vault and the strategy are deployed as separate contracts. Each is an actor that doesn't know the other's internal storage. They communicate only through the public surface declared here.

If you change a function signature later (add a parameter, change a return type), every concrete strategy and every vault that integrates with one breaks. The interface is the contract you live with for the lifetime of the deployment. You should be able to articulate why every function on each interface exists.

IStrategy, What the Vault Calls

interface IStrategy {
    function want() external view returns (address);
    function vault() external view returns (address);
    function estimatedTotalAssets() external view returns (uint256);
    function emergencyExit() external view returns (bool);
    function isActive() external view returns (bool);
    function withdraw(uint256 amountNeeded) external returns (uint256 loss);
    function setEmergencyExit() external;
    function migrate(address newStrategy) external;
}

Three reads (want, vault, estimatedTotalAssets) are how the vault validates and prices a strategy. The vault's addStrategy() calls vault() and want() to check the strategy is bound to it and uses the right underlying. estimatedTotalAssets() is what the vault asks during report() to compute gain/loss against totalDebt.

withdraw(amountNeeded) is how the vault drains a strategy on user withdraw. setEmergencyExit() and migrate() are governance hooks: a strategy in trouble is told to liquidate and return everything; a strategy being replaced hands off positions to the new strategy address.

IVaultAPI, What the Strategy Calls

interface IVaultAPI {
    function token() external view returns (address);
    function strategies(address strategy) external view returns (
        uint256 performanceFee,
        uint256 activation,
        uint256 debtRatio,
        uint256 minDebtPerHarvest,
        uint256 maxDebtPerHarvest,
        uint256 lastReport,
        uint256 totalDebt,
        uint256 totalGain,
        uint256 totalLoss
    );
    function creditAvailable() external view returns (uint256);
    function debtOutstanding() external view returns (uint256);
    function report(uint256 gain, uint256 loss, uint256 _debtPayment) external returns (uint256);
}

token() is how the strategy knows what to ask transferFrom for in its constructor. strategies(self) returns the strategy's own params (the StrategyParams tuple from section 2). creditAvailable() and debtOutstanding() (built in section 10) are the dynamic capital allocation. report(...) (built in section 11) is the central call.

Notice the asymmetry: the strategy depends on the vault, not the other way around. The vault treats strategies as black-box actors with a known interface; the strategy reads vault state (debt, credit) to know what to do.

Why This File Has No Contract

Sections 2-6 built the Vault* chain (each contract inheriting the previous). Section 8 will build BaseStrategy, the abstract parent of every concrete strategy. These are two separate deployable contracts, and the interfaces here let either side compile without needing the other.

If you tried to put a contract in this file and have section 8 inherit from it, you'd entangle the strategy chain with the vault chain. Interfaces decouple. Contracts couple.

What's Next

Section 8 builds BaseStrategy, the abstract contract that concrete strategies (Aave lender, Curve LP, Yearn-on-Yearn compounder) inherit from. It uses IVaultAPI from this file to talk back to its parent vault. Section 9 returns to the vault chain to register strategies with addStrategy.

Your Code

Solution.sol
Solidity
Loading editor...

Requirements

Write your implementation, then click Run Tests. Tests execute on the server.