Skip to main content

YieldSkimmingTokenizedStrategy

Git Source

Inherits: TokenizedStrategy

Author: Golem Foundation

Specialized TokenizedStrategy for yield-bearing assets (appreciating exchange rate).

*Mechanism:

  • Tracks value debt separately for users and dragon router (units: value-shares; 1 share = 1 asset value)
  • On report(), compares total vault value (assets * rate in RAY) vs total value debt (users + dragon) • Profit: mints value-shares to dragon and increases dragon value debt • Loss: burns dragon shares (if enabled and available) and reduces dragon value debt
  • Dual conversion modes: • Solvent: rate-based conversions using current exchange rate (RAY precision) • Insolvent: proportional distribution using base TokenizedStrategy logic; dragon operations blocked
  • Dragon transfers trigger value-debt rebalancing; self-transfers by dragon are disallowed*

Note: security-contact: [email protected]

State Variables

YIELD_SKIMMING_STORAGE_SLOT

bytes32 private constant YIELD_SKIMMING_STORAGE_SLOT =
bytes32(uint256(keccak256("octant.yieldSkimming.exchangeRate")) - 1);

Functions

deposit

Deposit assets into the strategy with value debt tracking

*Requirements:

  • Vault must be solvent (reverts otherwise)
  • Receiver cannot be dragon router (dragon shares minted via report())
  • Tracks asset value debt*
function deposit(uint256 assets, address receiver) external override nonReentrant returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of assets to deposit in asset base units
receiveraddressAddress to receive the shares (cannot be dragon router)

Returns

NameTypeDescription
sharesuint256Amount of shares minted (1 share = 1 asset value)

mint

Mint exact shares from the strategy with value debt tracking

Implements insolvency protection and tracks ETH value debt

function mint(uint256 shares, address receiver) external override nonReentrant returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of shares to mint
receiveraddressAddress to receive the shares

Returns

NameTypeDescription
assetsuint256Amount of assets deposited in asset base units (1 share = 1 ETH value)

redeem

Redeem shares from the strategy with default maxLoss

Wrapper that calls the full redeem function with MAX_BPS maxLoss

function redeem(uint256 shares, address receiver, address owner) external override returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of shares to redeem
receiveraddressAddress to receive the assets
owneraddressAddress whose shares are being redeemed

Returns

NameTypeDescription
assetsuint256Amount of assets returned in asset base units

redeem

Redeem shares from the strategy with value debt tracking

Shares represent ETH value (1 share = 1 ETH value)

function redeem(uint256 shares, address receiver, address owner, uint256 maxLoss)
public
override
nonReentrant
returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256Amount of shares to redeem
receiveraddressAddress to receive the assets
owneraddressAddress whose shares are being redeemed
maxLossuint256Maximum acceptable loss in basis points

Returns

NameTypeDescription
assetsuint256Amount of assets returned in asset base units

withdraw

Withdraw assets from the strategy with value debt tracking

Calculates shares needed for the asset amount requested

function withdraw(uint256 assets, address receiver, address owner, uint256 maxLoss)
public
override
nonReentrant
returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of assets to withdraw in asset base units
receiveraddressAddress to receive the assets
owneraddressAddress whose shares are being redeemed
maxLossuint256Maximum acceptable loss in basis points

Returns

NameTypeDescription
sharesuint256Amount of shares burned in share base units

withdraw

Withdraw assets from the strategy with default maxLoss

Wrapper that calls the full withdraw function with 0 maxLoss

function withdraw(uint256 assets, address receiver, address owner) external override returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256Amount of assets to withdraw in asset base units
receiveraddressAddress to receive withdrawn assets
owneraddressAddress whose shares are being redeemed

Returns

NameTypeDescription
sharesuint256Amount of shares burned in share base units

maxDeposit

Get the maximum amount of assets that can be deposited by a user

Returns 0 for dragon router as they cannot deposit

function maxDeposit(address receiver) public view override returns (uint256);

Parameters

NameTypeDescription
receiveraddressAddress that would receive the shares

Returns

NameTypeDescription
<none>uint256Maximum deposit amount in asset base units

maxMint

Get the maximum amount of shares that can be minted by a user

Returns 0 for dragon router as they cannot mint

function maxMint(address receiver) public view override returns (uint256);

Parameters

NameTypeDescription
receiveraddressAddress that would receive the shares

Returns

NameTypeDescription
<none>uint256Maximum mint amount in shares

maxWithdraw

Get the maximum amount of assets that can be withdrawn by a user

Returns 0 for dragon router during insolvency

function maxWithdraw(address owner) public view override returns (uint256);

Parameters

NameTypeDescription
owneraddressAddress whose shares would be burned

Returns

NameTypeDescription
<none>uint256Maximum withdraw amount in asset base units

maxRedeem

Get the maximum amount of shares that can be redeemed by a user

Returns 0 for dragon router during insolvency

function maxRedeem(address owner) public view override returns (uint256);

Parameters

NameTypeDescription
owneraddressAddress whose shares would be burned

Returns

NameTypeDescription
<none>uint256Maximum redeem amount in shares

getTotalUserDebtInAssetValue

Get the total ETH value debt owed to users

function getTotalUserDebtInAssetValue() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total user debt in asset value

getDragonRouterDebtInAssetValue

Get the total ETH value debt owed to dragon router

function getDragonRouterDebtInAssetValue() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total dragon router debt in asset value

getTotalValueDebtInAssetValue

Get the total ETH value debt owed to both users and dragon router combined

function getTotalValueDebtInAssetValue() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total debt in asset value combining users and dragon router

transfer

Transfer shares with dragon solvency protection and debt rebalancing

*Special behaviors for dragon router:

  • Dragon cannot transfer to itself (reverts)
  • Dragon transfers trigger value debt rebalancing
  • Dragon can only transfer when vault is solvent For non-dragon transfers, behaves like standard ERC20 transfer*
function transfer(address to, uint256 amount) external override returns (bool success);

Parameters

NameTypeDescription
toaddressAddress receiving shares
amountuint256Amount of shares to transfer

Returns

NameTypeDescription
successboolWhether transfer succeeded

transferFrom

Transfer shares from one address to another with dragon solvency protection and debt rebalancing

*Special behaviors for dragon router:

  • Dragon cannot transfer to itself (reverts)
  • Dragon transfers trigger value debt rebalancing
  • Dragon can only transfer when vault is solvent For non-dragon transfers, behaves like standard ERC20 transferFrom*
function transferFrom(address from, address to, uint256 amount) external override returns (bool success);

Parameters

NameTypeDescription
fromaddressAddress transferring shares
toaddressAddress receiving shares
amountuint256Amount of shares to transfer

Returns

NameTypeDescription
successboolWhether transfer succeeded

report

Reports yield skimming strategy performance and handles value debt adjustments

*Overrides report to handle yield appreciation and loss recovery using value debt approach. Health check effectiveness depends on report() frequency. Exchange rate checks become less effective over time if reports are infrequent, as profit limits may be exceeded. Management should ensure regular reporting or adjust profit/loss ratios based on expected frequency. Key behaviors:

  1. Value Debt Tracking: Compares current total value (assets * exchange rate) vs total debt (user debt + dragon router debt combined)
  2. Profit Capture: When current value exceeds total debt, mints shares to dragonRouter and increases dragon debt accordingly
  3. Loss Protection: When current value is less than total debt, burns dragon shares (up to available balance) and reduces dragon debt
  4. Insolvency Handling: If dragon buffer insufficient for losses, remaining shortfall is handled through proportional asset distribution during withdrawals, not by modifying debt balances*
function report() public override(TokenizedStrategy) nonReentrant onlyKeepers returns (uint256 profit, uint256 loss);

Returns

NameTypeDescription
profituint256Profit in assets from underlying value appreciation
lossuint256Loss in assets from underlying value depreciation

getLastRateRay

Get the last reported exchange rate (RAY precision)

function getLastRateRay() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Last reported exchange rate in RAY precision

isVaultInsolvent

Check if the vault is currently insolvent

function isVaultInsolvent() external view returns (bool);

Returns

NameTypeDescription
<none>boolisInsolvent True if vault cannot cover user value debt and dragon router debt

_deposit

Internal deposit function that handles asset transfers and share minting

function _deposit(StrategyData storage S, address receiver, uint256 assets, uint256 shares) internal override;

Parameters

NameTypeDescription
SStrategyDataStrategy data storage reference
receiveraddressAddress receiving minted shares
assetsuint256Amount of assets being deposited in asset base units
sharesuint256Amount of shares to mint

_convertToShares

Converts assets to shares using value debt approach with solvency awareness

function _convertToShares(StrategyData storage S, uint256 assets, Math.Rounding rounding)
internal
view
virtual
override
returns (uint256);

Parameters

NameTypeDescription
SStrategyDataStrategy storage
assetsuint256Amount of assets to convert
roundingMath.RoundingRounding mode for division

Returns

NameTypeDescription
<none>uint256Amount of shares equivalent in value (1 share = 1 ETH value)

_convertToAssets

Converts shares to assets using value debt approach with solvency awareness

function _convertToAssets(StrategyData storage S, uint256 shares, Math.Rounding rounding)
internal
view
virtual
override
returns (uint256);

Parameters

NameTypeDescription
SStrategyDataStrategy storage
sharesuint256Amount of shares to convert
roundingMath.RoundingRounding mode for division

Returns

NameTypeDescription
<none>uint256Amount of assets user would receive in asset base units

_isVaultInsolvent

Checks if the vault is currently insolvent

function _isVaultInsolvent() internal view returns (bool isInsolvent);

Returns

NameTypeDescription
isInsolventboolTrue if vault cannot cover user value debt

_rebalanceDebtOnDragonTransfer

Rebalances debt tracking when dragon transfers shares in or out

function _rebalanceDebtOnDragonTransfer(address from, address to, uint256 transferAmount) internal;

_requireDragonSolvency

Blocks dragon router from withdrawing during vault insolvency

function _requireDragonSolvency(address account) internal view;

Parameters

NameTypeDescription
accountaddressAddress to check (only blocks if it's dragon router)

_requireVaultSolvency

Blocks all operations when vault is insolvent

function _requireVaultSolvency() internal view;

_currentRateRay

Get the current exchange rate scaled to RAY precision

function _currentRateRay() internal view virtual returns (uint256);

Returns

NameTypeDescription
<none>uint256Current exchange rate in RAY format (1e27 = 1.0)

_handleDragonLossProtection

Internal function to handle loss protection by burning dragon shares

function _handleDragonLossProtection(
StrategyData storage S,
YieldSkimmingStorage storage YS,
uint256 lossValue,
uint256 currentRate
) internal returns (uint256 loss);

Parameters

NameTypeDescription
SStrategyDataStrategy storage pointer
YSYieldSkimmingStorageYield skimming storage pointer
lossValueuint256Loss amount in ETH value terms
currentRateuint256Current exchange rate in RAY format

Returns

NameTypeDescription
lossuint256Loss amount in asset terms for reporting

finalizeDragonRouterChange

Finalizes the dragon router change with proper debt accounting migration

Migrates debt tracking when dragon router changes to maintain correct accounting

function finalizeDragonRouterChange() external override;

_strategyYieldSkimmingStorage

function _strategyYieldSkimmingStorage() internal pure returns (YieldSkimmingStorage storage S);

Events

Harvest

Event emitted when harvest is performed

event Harvest(address indexed caller, uint256 currentRate);

DonationMinted

Events for donation tracking

event DonationMinted(address indexed dragonRouter, uint256 amount, uint256 exchangeRate);

Parameters

NameTypeDescription
dragonRouteraddressAddress receiving or burning donation shares
amountuint256Amount of value-shares minted or burned (1 share = 1 value unit)
exchangeRateuint256Current exchange rate (scaled to wad) at the time of the event

DonationBurned

Emitted when dragon shares are burned to cover value losses

event DonationBurned(address indexed dragonRouter, uint256 amount, uint256 exchangeRate);

Structs

YieldSkimmingStorage

Storage for yield skimming strategy

struct YieldSkimmingStorage {
uint256 totalUserDebtInAssetValue;
uint256 lastReportedRate;
uint256 dragonRouterDebtInAssetValue;
}