Convex Finance Protocol Adapter
The Convex adapter enables the Yieldinator Facet to integrate with Convex Finance, allowing vaults to earn boosted CRV rewards and additional CVX rewards by staking Curve LP tokens in Convex pools.
Overview
Convex Finance is a protocol built on top of Curve Finance that provides boosted rewards for Curve LP token holders. By staking Curve LP tokens through Convex, users can earn higher CRV rewards without needing to lock CRV tokens themselves, as well as additional CVX token rewards. The Convex adapter facilitates deposits into Convex pools, manages staked positions, and harvests both CRV and CVX rewards.
Implementation Details
Contract: ConvexAdapter.sol
ConvexAdapter.solThe adapter implements the standard YieldinatorAdapter interface with Convex-specific functionality:
contract ConvexAdapter is YieldinatorAdapter {
// Convex contracts
IConvexBooster public convexBooster;
address public cvxToken;
address public crvToken;
// Pool configuration
struct PoolConfig {
uint256 pid; // Convex pool ID
address lpToken; // Curve LP token address
address rewardContract; // Convex reward contract
bool active; // Whether the pool is active
}
// Mapping from token (Curve LP token) to pool configuration
mapping(address => PoolConfig) public tokenToPool;
// Deposited amounts per token
mapping(address => uint256) public depositedAmount;
// Constructor and core functions...
}Key Functions
Pool Registration
Before using the adapter for a specific Curve LP token, the Convex pool must be registered:
function registerPool(address _token, uint256 _pid) external onlyRole(ADAPTER_ADMIN_ROLE)The function:
Retrieves pool information from the Convex booster contract
Verifies the pool is not shutdown
Confirms the LP token address matches the provided token
Stores the pool configuration for future use
Deposit
Deposits Curve LP tokens into Convex:
function deposit(address _token, uint256 _amount) external override onlyRole(YIELDINATOR_ROLE) nonReentrant returns (bool)The function:
Transfers LP tokens from the caller to the adapter
Approves the Convex booster to spend the LP tokens
Deposits LP tokens into Convex and automatically stakes them in the rewards contract
Updates the deposited amount tracking
Withdraw
Withdraws LP tokens from Convex:
function withdraw(address _token, uint256 _amount) external override onlyRole(YIELDINATOR_ROLE) nonReentrant returns (bool)The function:
Withdraws LP tokens from the Convex rewards contract
Withdraws LP tokens from the Convex booster
Transfers LP tokens to the caller
Updates the deposited amount tracking
Harvest Yield
Harvests CRV, CVX, and any additional rewards:
function harvestYield(address _token) external override onlyRole(YIELDINATOR_ROLE) nonReentrant returns (uint256)The function:
Claims rewards from the Convex rewards contract
Transfers CRV tokens to the caller
Transfers CVX tokens to the caller
Attempts to claim and transfer any additional reward tokens
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 Convex:
function getCurrentAPY(address _token) external view override returns (uint256)Note: In a production environment, this would require external data sources to calculate accurately.
Additional Functions
The adapter includes additional Convex-specific functions:
function getClaimableRewards(address _token) external view returns (uint256, uint256)
function deactivatePool(address _token) external onlyRole(ADAPTER_ADMIN_ROLE)
function reactivatePool(address _token) external onlyRole(ADAPTER_ADMIN_ROLE)Usage Example
// Initialize the adapter
ConvexAdapter convexAdapter = new ConvexAdapter(
convexBoosterAddress,
cvxTokenAddress,
crvTokenAddress,
adminAddress
);
// Register a pool
convexAdapter.registerPool(curve3PoolLpTokenAddress, 3); // Pool ID 3 for 3pool
// Deposit LP tokens
convexAdapter.deposit(curve3PoolLpTokenAddress, 1000 * 1e18);
// After some time, harvest yield
uint256 harvestedYield = convexAdapter.harvestYield(curve3PoolLpTokenAddress);
// Withdraw LP tokens
convexAdapter.withdraw(curve3PoolLpTokenAddress, 500 * 1e18);
// In case of emergency
convexAdapter.emergencyWithdraw(curve3PoolLpTokenAddress);
// Check claimable rewards
(uint256 claimableCrv, uint256 claimableCvx) = convexAdapter.getClaimableRewards(curve3PoolLpTokenAddress);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 includes pool activation/deactivation functionality to handle potential issues with Convex pools.
Gas Optimization
The adapter deposits and stakes LP tokens in a single transaction to save gas.
Token approvals are set exactly to the amount being deposited to avoid unnecessary approvals.
The adapter claims all rewards in a single transaction during yield harvesting.
Integration Requirements
To use the Convex adapter, the following components are required:
The Convex Booster contract address
The CVX token address
The CRV token address
Convex pool IDs for the target Curve LP tokens
Proper role assignments for the Yieldinator Facet
Reward Mechanism
Convex provides two primary types of rewards:
CRV Rewards: Boosted CRV rewards from Curve gauges
CVX Rewards: Additional CVX tokens minted based on CRV rewards
The adapter handles both reward types and can also claim additional rewards that may be distributed through Convex (e.g., SNX, SPELL, etc.).