Compound Protocol Adapter

The Compound adapter enables the Yieldinator Facet to integrate with Compound's money markets, allowing vaults to earn yield by supplying assets to Compound's lending protocol.

Overview

Compound is a decentralized lending protocol that allows users to supply assets to earn interest and borrow assets against collateral. The Compound adapter facilitates deposits into Compound markets, manages cToken balances, and harvests yield generated from lending interest and COMP token rewards.

Implementation Details

Contract: CompoundAdapter.sol

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

contract CompoundAdapter is YieldinatorAdapter {
    // Compound contracts
    IComptroller public comptroller;
    address public compToken;
    
    // Mapping from underlying asset to cToken
    mapping(address => address) public assetToCToken;
    
    // Deposited amounts per token
    mapping(address => uint256) public depositedAmount;
    
    // Constructor and core functions...
}

Key Functions

Asset Registration

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

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

Deposit

Deposits tokens into Compound's money markets:

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 cToken contract to spend the tokens

  3. Mints cTokens by supplying the underlying asset

  4. Updates the deposited amount tracking

Withdraw

Withdraws tokens from Compound's money markets:

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

Harvest Yield

Harvests accrued interest and COMP rewards:

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

The function:

  1. Calculates yield based on the exchange rate between cTokens and the underlying asset

  2. Redeems only the yield portion, leaving the principal intact

  3. Claims COMP token rewards from the Comptroller

  4. Transfers both the yield and COMP rewards 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 Compound:

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

The APY is calculated based on Compound's supplyRatePerBlock, converted to an annual percentage with 2 decimal places (scaled by 10000).

Additional Functions

The adapter includes additional Compound-specific functions:

function getCToken(address _asset) external view returns (address)
function getAccruedComp() external view returns (uint256)

Usage Example

// Initialize the adapter
CompoundAdapter compoundAdapter = new CompoundAdapter(comptrollerAddress, compTokenAddress, adminAddress);

// Register an asset
compoundAdapter.registerAsset(daiAddress, cDaiAddress);

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

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

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

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

// Check accrued COMP rewards
uint256 pendingComp = compoundAdapter.getAccruedComp();

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 checks Compound operation result codes to ensure successful execution.

Gas Optimization

  • The adapter minimizes the number of external calls to Compound contracts.

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

  • COMP rewards are claimed in the same transaction as yield harvesting to save gas.

Integration Requirements

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

  1. A Compound Comptroller address for the target network

  2. The COMP token address

  3. The corresponding cToken addresses for each asset

  4. Proper role assignments for the Yieldinator Facet