Yearn Finance Protocol Adapter

The Yearn adapter enables the Yieldinator Facet to integrate with Yearn Finance's yield-optimizing vaults, allowing vaults to benefit from Yearn's automated yield strategies across multiple DeFi protocols.

Overview

Yearn Finance is a suite of products in DeFi that provides yield generation, lending aggregation, and more. The core product is the Yearn Vault (yVault), which automatically moves funds between different lending and liquidity protocols to find the highest yield. The Yearn adapter facilitates deposits into Yearn vaults, manages share balances, and harvests yield generated by Yearn's strategies.

Implementation Details

Contract: YearnAdapter.sol

The adapter implements the standard YieldinatorAdapter interface with Yearn-specific functionality:

contract YearnAdapter is YieldinatorAdapter {
    // Mapping from underlying asset to Yearn vault
    mapping(address => address) public assetToVault;
    
    // Deposited amounts per token
    mapping(address => uint256) public depositedAmount;
    
    // Shares per token
    mapping(address => uint256) public sharesPerToken;
    
    // Constructor and core functions...
}

Key Functions

Asset Registration

Before using the adapter for a specific token, the asset must be registered with its corresponding Yearn vault:

function registerAsset(address _asset, address _vault) external onlyRole(ADAPTER_ADMIN_ROLE)

Deposit

Deposits tokens into a Yearn vault:

function deposit(address _token, uint256 _amount) external override onlyRole(YIELDINATOR_ROLE) nonReentrant returns (bool)

The function:

  1. Transfers tokens from the caller to the adapter

  2. Approves the vault to spend the tokens

  3. Deposits tokens into the Yearn vault

  4. Tracks the shares received from the deposit

  5. Updates the deposited amount tracking

Withdraw

Withdraws tokens from a Yearn vault:

function withdraw(address _token, uint256 _amount) external override onlyRole(YIELDINATOR_ROLE) nonReentrant returns (bool)

The function:

  1. Calculates shares to withdraw based on the current pricePerShare

  2. Withdraws tokens from the Yearn vault by redeeming shares

  3. Transfers tokens to the caller

  4. Updates the deposited amount and shares tracking

Harvest Yield

Harvests yield generated by the Yearn vault:

function harvestYield(address _token) external override onlyRole(YIELDINATOR_ROLE) nonReentrant returns (uint256)

The function:

  1. Calculates the current value of shares based on pricePerShare

  2. If the current value exceeds the deposited amount, the difference is yield

  3. Calculates shares to withdraw for the yield portion

  4. Withdraws only the yield portion from the Yearn vault

  5. Transfers yield to the caller

Emergency Withdraw

Provides emergency withdrawal functionality:

function emergencyWithdraw(address _token) external override onlyRole(YIELDINATOR_ROLE) nonReentrant returns (uint256)

APY Calculation

Returns the current APY for a token in Yearn:

function getCurrentAPY(address _token) external view override returns (uint256)

Note: In a production environment, this would require historical data or an API call to calculate accurately.

Additional Functions

The adapter includes additional Yearn-specific functions:

function getCurrentValue(address _token) external view returns (uint256)
function getVault(address _asset) external view returns (address)

Usage Example

// Initialize the adapter
YearnAdapter yearnAdapter = new YearnAdapter(adminAddress);

// Register an asset
yearnAdapter.registerAsset(daiAddress, daiVaultAddress);

// Deposit tokens
yearnAdapter.deposit(daiAddress, 1000 * 1e18);

// After some time, harvest yield
uint256 harvestedYield = yearnAdapter.harvestYield(daiAddress);

// Withdraw tokens
yearnAdapter.withdraw(daiAddress, 500 * 1e18);

// In case of emergency
yearnAdapter.emergencyWithdraw(daiAddress);

// Check current value of deposits
uint256 currentValue = yearnAdapter.getCurrentValue(daiAddress);

Security Considerations

  • The adapter uses OpenZeppelin's SafeERC20 for token transfers to prevent common ERC20 vulnerabilities.

  • Non-reentrancy guards protect against reentrancy attacks during external calls.

  • Role-based access control ensures only authorized addresses can call sensitive functions.

  • The adapter maintains accurate tracking of shares to ensure correct yield calculation.

Gas Optimization

  • The adapter tracks shares separately from deposited amounts to minimize calculations.

  • Token approvals are set exactly to the amount being deposited to avoid unnecessary approvals.

  • The adapter calculates share values only when needed to save gas.

Integration Requirements

To use the Yearn adapter, the following components are required:

  1. Yearn vault addresses for the target assets

  2. Proper role assignments for the Yieldinator Facet

Yield Calculation

The Yearn adapter calculates yield based on the increase in the value of shares over time:

  1. When tokens are deposited, the adapter receives shares from the Yearn vault.

  2. The value of these shares increases over time as the vault generates yield.

  3. The adapter tracks the original deposit amount and compares it to the current value of shares.

  4. The difference between these values represents the yield.

This approach ensures that all yield generated by Yearn's strategies is captured, regardless of the source (lending interest, trading fees, farming rewards, etc.).