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
YearnAdapter.solThe 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:
Transfers tokens from the caller to the adapter
Approves the vault to spend the tokens
Deposits tokens into the Yearn vault
Tracks the shares received from the deposit
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:
Calculates shares to withdraw based on the current pricePerShare
Withdraws tokens from the Yearn vault by redeeming shares
Transfers tokens to the caller
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:
Calculates the current value of shares based on pricePerShare
If the current value exceeds the deposited amount, the difference is yield
Calculates shares to withdraw for the yield portion
Withdraws only the yield portion from the Yearn vault
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:
Yearn vault addresses for the target assets
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:
When tokens are deposited, the adapter receives shares from the Yearn vault.
The value of these shares increases over time as the vault generates yield.
The adapter tracks the original deposit amount and compares it to the current value of shares.
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.).