β¨ Yield Farming Aggregator π
A cutting-edge decentralized application (dApp) designed to empower users with intelligent yield optimization in the DeFi ecosystem. This platform aggregates yield opportunities across multiple protocols, presenting them in a clear, comparative dashboard. It serves as the foundation for advanced features like automated strategy switching and auto-compounding, helping users maximize their crypto earnings with minimal effort.
- Project Overview
- Key Features
- Architecture
- Technologies Used
- Getting Started
- Usage
- Testing
- Security-Analysis-Report-(Aderyn)
- Contributing
- License
- Author-Info
This project is a sophisticated Yield Farming Aggregator, a decentralized application built on Solidity smart contracts and a modern React/Next.js frontend. It's engineered to provide users with a comprehensive overview of yield-generating opportunities across various DeFi protocols. The backend smart contracts facilitate secure asset deposits, withdrawals, and future auto-compounding and strategy switching, while the intuitive frontend dashboard empowers users to identify and engage with the most profitable yields efficiently. The goal is to simplify complex DeFi strategies, making yield farming accessible and optimized for everyone.
- Multi-Protocol Yield Aggregation: Seamlessly connects to various DeFi protocols like Aave V3 and Compound V3 through modular adapter contracts.
- Dynamic Yield Comparison Dashboard: Provides real-time APY (Annual Percentage Yield) and TVL (Total Value Locked) data, enabling users to compare and select the best investment opportunities.
- Automated Strategy Management (Planned): Future-proofed with a
StrategyManagercontract to enable intelligent decision-making for auto-compounding rewards and automatically switching to higher-yielding protocols. - Robust Security Measures: Implements
OwnableandReentrancyGuardfrom OpenZeppelin to safeguard contract ownership and prevent common vulnerabilities. - Intuitive User Interface: A responsive and modern frontend built with Next.js, React, and Tailwind CSS, offering a smooth user experience for viewing, searching, and managing investments.
- Token Agnostic Adapters: Designed with flexible protocol adapters to support various ERC20 tokens for deposits and withdrawals.
The project follows a robust architecture, separating concerns between the smart contract logic and the user-facing frontend.
The core logic resides in a suite of Solidity smart contracts, managed with Foundry.
YieldAggregator.sol: The central hub, responsible for managing user positions, interacting with protocol adapters, and handling deposits/withdrawals. It includesOwnableandReentrancyGuardfor security.StrategyManager.sol: An immutable contract that encapsulates the logic for identifying the best yield opportunities across protocols and calculating the benefits of strategy switches.IProtocolAdapter.sol: An interface defining the standard functions (deposit, withdraw) that all protocol-specific adapters must implement.AaveV3Adapter.sol&CompoundV3Adapter.sol: Concrete implementations ofIProtocolAdapterto interact with Aave V3 and Compound V3 protocols, respectively.IComet.sol: A minimalistic interface for interacting with Compound's Comet protocol.OracleLib.sol: A placeholder library for future price oracle integrations.
The user interface is a modern React application built with Next.js, providing a seamless experience.
components/: Houses reusable UI components likeHeader,Dashboard,YieldTable,SummaryCards,SearchBar, andFooter.hooks/: Contains custom React hooks, notablyuseProtocolRatesfor fetching and managing protocol data from external APIs like DeFiLlama.contexts/: Manages global state, such asThemeContextfor dark/light mode functionality.app/: Next.js specific routing and layout for pages.- Web3 Integration: Utilizes
wagmiandRainbowKitfor secure and user-friendly wallet connection across various chains (Ethereum mainnet, Optimism, Arbitrum, Base, ZkSync, Sepolia, Anvil).
| Category | Technology | Description | Link |
|---|---|---|---|
| Smart Contracts | Solidity | Primary language for smart contract development. | Solidity |
| Foundry | Fast, portable, and modular toolkit for Ethereum development. | Foundry | |
| OpenZeppelin | Library for secure smart contract development (Ownable, ERC20). | OpenZeppelin | |
| Frontend | React | JavaScript library for building user interfaces. | React |
| Next.js | React framework for production-grade applications. | Next.js | |
| TypeScript | Strongly typed JavaScript for enhanced code quality. | TypeScript | |
| Tailwind CSS | Utility-first CSS framework for rapid UI development. | Tailwind CSS | |
| Wagmi | React Hooks for Ethereum. | Wagmi | |
| RainbowKit | React library for wallet connection UI. | RainbowKit | |
| Viem | TypeScript Interface for Ethereum. | Viem | |
| Zustand | Lightweight state management library for React. | Zustand | |
| React Query | Hooks for fetching, caching, and updating asynchronous data. | React Query | |
| Data & APIs | DeFiLlama API | Aggregated DeFi data for protocol rates. | DeFiLlama |
| Development | Node.js | JavaScript runtime for backend and tooling. | Node.js |
| npm/Yarn | Package managers. | npm | |
| Git | Version control system. | Git |
Follow these instructions to set up and run the project locally for both smart contract development and the frontend application.
Before you begin, ensure you have the following installed on your system:
- π’ Node.js (LTS version recommended) &
npm(oryarn) - π οΈ Foundry: Install
foundryupto manage Foundry tools (Forge, Cast, Anvil, Chisel).curl -L https://foundry.paradigm.xyz | bash foundryup - π Git: For cloning the repository.
Start by cloning the project repository to your local machine:
git clone https://github.com/Kelechikizito/yield-farming-aggregator-foundry.git
cd yield-farming-aggregator-foundryNavigate to the root of the project and install Foundry dependencies:
forge install
# This will install submodules defined in .gitmodules, like OpenZeppelin, forge-std, aave-v3-core, etc.Navigate into the frontend directory and install its dependencies:
cd frontend
npm install # or yarn install
cd .. # Go back to root directoryCreate a .env file in the root directory and a .env.local file in the frontend directory based on the examples below.
Root .env (for Foundry):
# Ethereum Sepolia RPC URL (e.g., from Alchemy, Infura)
SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_URL"
# Arbitrum Sepolia RPC URL
ARBITRUM_SEPOLIA_RPC_URL="YOUR_ARBITRUM_SEPOLIA_RPC_URL"
# ZkSync Sepolia RPC URL
ZKSYNC_SEPOLIA_RPC_URL="YOUR_ZKSYNC_SEPOLIA_RPC_URL"
# Private key for deployment and interactions (e.g., from Metamask, should start with 0x)
PRIVATE_KEY="YOUR_PRIVATE_KEY"
frontend/.env.local (for Next.js/RainbowKit):
# WalletConnect Project ID (Get one from cloud.walletconnect.com)
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID="YOUR_WALLETCONNECT_PROJECT_ID"
You can run tests for the smart contracts using Forge:
forge testTo deploy the contracts to a testnet (e.g., Sepolia), you would use a command similar to this (ensure your PRIVATE_KEY and SEPOLIA_RPC_URL are set in .env):
# Example deployment command (actual script might be more complex)
# forge script script/DeployAggregator.s.sol --rpc-url $SEPOLIA_RPC_URL --private-key $PRIVATE_KEY --broadcast --verifyNote: Specific deployment scripts are not provided in the codebase, you would typically write one in the script/ directory.
Navigate back to the frontend directory and start the Next.js development server:
cd frontend
npm run dev # or yarn devThe frontend application will be accessible at http://localhost:3000.
- Connect Wallet: Open the frontend application in your browser (e.g.,
http://localhost:3000). Click the "Connect Wallet" button in the header and select your preferred wallet (e.g., MetaMask). - View Dashboard: Once connected, the dashboard will display a table of yield opportunities from various protocols. You can sort by APY, TVL, and other metrics.
- Explore Yields: Browse the "Yield Opportunities" table to discover protocols, asset types, APY, TVL, and risk levels.
- Simulated Farming: Click "Start Farming" buttons next to a protocol to simulate an investment flow. (Note: Actual investment functionality requires further smart contract integration beyond the current MVP).
As a developer, you can interact with the deployed YieldAggregator contract:
Add a new protocol adapter address to the aggregator.
- HTTP METHOD: (Not applicable, direct contract call)
- Function Call:
YieldAggregator.addAdapter(string protocolName, address adapterAddress) - Permissions:
onlyOwner
Configure auto-compounding preferences for your address.
- HTTP METHOD: (Not applicable, direct contract call)
- Function Call:
YieldAggregator.setAutoCompoundSettings(bool enabled, uint256 minReward, uint256 maxGas, uint256 slippage)
Deposit tokens into a yield-generating protocol.
- HTTP METHOD: (Not applicable, direct contract call)
- Function Call:
YieldAggregator.invest(address token, uint256 amount, string preferredProtocol)token: Address of the ERC20 token to invest (e.g., USDC, DAI).amount: Amount of tokens to invest.preferredProtocol: Name of the target protocol (e.g., "compound", "aave"). Leave empty for StrategyManager to pick the best.
- Request: (Solidity transaction data)
// Example transaction using cast/ethers.js/web3.js YieldAggregatorContract.invest(USDC_ADDRESS, 1000 * 10**6, "compound-v3"); // For 1000 USDC
- Response:
uint256 shares(amount of protocol-specific shares received) - Errors:
YieldAggregator__InsufficientBalance(): Sender's token balance is too low.YieldAggregator__ProtocolNotSupported(): No adapter registered for the specified protocol.YieldAggregator__InvalidAmount(): Amount is zero.YieldAggregator__InvalidToken(): Token address is zero.YieldAggregator__InvalidSharesReceived(): Adapter returned zero shares.
Withdraw funds from a specific investment position.
- HTTP METHOD: (Not applicable, direct contract call)
- Function Call:
YieldAggregator.withdraw(uint256 positionIndex)positionIndex: The index of the user's position to withdraw from (usegetUserPositionsto find this).
- Request: (Solidity transaction data)
// Example transaction YieldAggregatorContract.withdraw(0); // Withdraw from the first position
- Response: (Transaction success)
- Errors:
YieldAggregator__PositionNotFound(): InvalidpositionIndex.YieldAggregator__ProtocolNotSupported(): Adapter not found for the protocol.
Admin function to withdraw accidental ETH sent to the contract (edge case).
- HTTP METHOD: (Not applicable, direct contract call)
- Function Call:
YieldAggregator.withdrawETH(address payable to, uint256 amount) - Permissions:
onlyOwner - Errors:
YieldAggregator__InsufficientETHBalance(): Contract has insufficient ETH.YieldAggregator__FailedETHWithdrawal(): ETH transfer failed.
getUserPositions(address user): Returns an array ofUserPositionstructs for a given user.getUserPositionCount(address user): Returns the total number of investment positions for a user.getUserPositionByIndex(address user, uint256 index): Returns a specificUserPositionstruct by index.
Comprehensive testing is crucial for smart contracts and the frontend:
- π§ͺ Smart Contract Unit Tests: Implemented using Foundry Forge, located in
test/unit/YieldAggregatorTest.t.sol. These tests cover core functionalities like investment, withdrawal, and adapter management. - π Frontend E2E & Unit Tests: (Planned) Implement end-to-end and unit tests for the React application using testing frameworks like Jest, React Testing Library, and Cypress/Playwright for E2E.
A static analysis report generated by Aderyn identified the following low-severity issues, which are important considerations for further development and auditing:
- L-1: Centralization Risk: Ownership via
Ownablegrants privileged roles (e.g., adding adapters, withdrawing ETH) to a single address. This is a common design pattern but implies trust in the owner. - L-2: Unsafe ERC20 Operation: Direct
transferFromwithout usingSafeERC20could be problematic with non-standard tokens. The project utilizes OpenZeppelin'sSafeERC20for many operations, but one instance inCompoundV3Adapter.solwas flagged. - L-3: Modifier Invoked Only Once: Modifiers
validAmountandvalidTokeninYieldAggregator.solare currently invoked only once. Consider inlining their logic for simplicity if they remain single-use. - L-4: Empty Block: Several internal functions in
StrategyManager.solandAaveV3Adapter.solcontain empty logic blocks ({}), indicating placeholder or incomplete implementations. - L-5: Missing Inheritance:
StrategyManagercontract does not explicitly inheritIStrategyManager, which might be intended for interface adherence. - L-6: Unchecked Return: Return values from internal calls to
_findBestYield,_calculateSwitchBenefit,_isProtocolSafe(inStrategyManager.sol) andIERC20(token).transferFrom(inCompoundV3Adapter.sol) are currently ignored.
These findings highlight areas for refinement to enhance robustness and security, especially as the project evolves.
Contributions are always welcome! If you have ideas for improvements, new features, or bug fixes, please follow these steps:
- π΄ Fork the repository.
- π Star the project!
- πΏ Create a new feature branch (
git checkout -b feature/AmazingFeature). - π» Commit your changes (
git commit -m 'Add some AmazingFeature'). - π Push to the branch (
git push origin feature/AmazingFeature). - π Open a Pull Request.
Please ensure your code adheres to the existing style and pass all tests.
Distributed under the MIT License. See the project repository for more details.
Kelechi Kizito Ugwu