Yield Accrual in V3 Strategies
This page describes how yield accrues and is accounted in Yearn V3. Yield can accrue continuously in external protocols, but it is only recognized in accounting when report() runs, with tend() available for maintenance between reports. For the broader system context, see V3 Overview.
Overview
- Yield accrues off-chain or in external protocols. This changes the strategy's real holdings but not its recorded accounting.
strategy.report()is called by a keeper or management. The strategy harvests, computes a total asset value, and updates internal accounting.vault.process_report(strategy)is called by the vault’s reporting manager. The vault reads the strategy’s ERC-4626 value and realizes gain or loss against its recorded debt, charging fees and locking profits at the vault level.
tend() fits between reports as a maintenance hook and does not change PPS or recorded profits until the next report().
Strategy accounting (Tokenized Strategy)
report()
In TokenizedStrategy.sol, report():
- Calls
BaseStrategy.harvestAndReport()to harvest, reinvest, and return a trustedtotalAssetssnapshot. - Compares the new
totalAssetsto the previous value to derive profit or loss. - Applies performance fees (and protocol fee on those fees).
- Locks profit in shares so PPS doesn’t jump, then unlocks over
profitMaxUnlockTime. - Updates
totalAssetsandlastReport.
Profits do not exist in accounting until report() is run. Losses can be realized on report() or during withdraw()/redeem().
Key code references:
TokenizedStrategy.sol→report()BaseStrategy.sol→harvestAndReport()
tend()
In TokenizedStrategy.sol, tend():
- Requires a keeper or management role.
- Calls
BaseStrategy.tendThis(_totalIdle), passing the strategy’s current idle balance. - Does not change
totalAssets, PPS, or accounting.
This is meant for actions like harvesting rewards or repositioning that should not yet be realized as profit or loss. A later report() finalizes accounting. For implementation details, see the Strategy Writing Guide.
Key code references:
TokenizedStrategy.sol→tend()BaseStrategy.sol→tendThis()and_tend()
Vault accounting (Allocator Vault)
V3 vaults treat strategies as ERC-4626 positions. In VaultV3.vy, process_report(strategy):
- Reads the vault’s strategy share balance and uses the strategy’s
convertToAssets()to compute current position value. - Compares that value to the vault’s recorded debt for the strategy to compute gain or loss.
- Invokes the accountant (if set) to calculate fees or refunds. See Periphery Contracts for how the accountant is configured.
- Locks profit at the vault level using vault shares and
profit_max_unlock_time. - Updates per-strategy accounting (including
last_report) and vault totals.
This means a strategy’s profit only becomes visible to vault depositors after process_report() is called, even if the strategy already reported.
Key code references:
VaultV3.vy→_process_report()VaultV3.vy→process_report()
Recommended cadence
- Report cadence should align with
profitMaxUnlockTime(strategy) andprofit_max_unlock_time(vault) so users see smooth, predictable unlocks. - Call order in practice:
strategy.report()vault.process_report(strategy)
- Use
tend()when needed for maintenance that should not immediately affect PPS.
Notes for strategists
- Only
report()realizes profit. Losses can be realized onreport()or duringwithdraw()/redeem(). Your_harvestAndReport()implementation defines what “realized” means for your strategy. tend()is for safety and efficiency, not accounting. Use it for rebalances, reward compounding, or moving idle funds when a full report would be premature. For more guidance, see the Strategy Writing Guide.- ERC-4626 conversion accuracy matters because the vault uses
convertToAssets()to determine gains or losses against debt.
Implementation checklist
- Implement
_harvestAndReport()to return a trusted, accurate total asset value. - If you use
_tend(), also implement_tendTrigger()and expect no accounting change until report. - Ensure keepers call
report()andvault.process_report()on a consistent schedule. - Consider how profit locking interacts with your reporting frequency and strategy liquidity.