STEP 2 - Strategy Development

Follow the following steps to develop the strategy.

  1. Fork the Clip Finance StrategyRouter repo.

  2. Add a new contract with the name of the strategy to contracts/strategies/.

  3. Write a new strategy contract in the new folder, making sure to include the necessary functions and structure as demonstrated in the previous strategies (e.g., deposit, withdraw, withdrawAll, compound, etc.). Ensure that you are using the appropriate libraries provided below.

  4. Write tests in the contracts/tests/strategies/ for your new strategy contract, ensuring comprehensive coverage of all essential aspects, such as depositing tokens, withdrawing tokens, compounding tokens, etc.

  5. Make a Pull Request with the changes on your fork, to the main Clip Finance StrategyRouter repo, with a comprehensive explanation of the strategy.

  6. Head over to the governance forum and submit your strategy.

By following this process, you can ensure that your DeFi project is listed on Clip Finance and that it adheres to the standard structure and best practices for strategy contracts within the Clip Finance ecosystem.

  1. @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol: This library provides a set of utility functions to interact with ERC20 tokens safely. The SafeERC20 library ensures that interactions with tokens are handled correctly and do not result in unexpected behavior.

  2. @openzeppelin/contracts/access/Ownable.sol: This library provides the Ownable contract, which is a widely-used access control mechanism

  3. ../StrategyRouter.sol: This library defines the StrategyRouter contract. The StrategyRouter contract is responsible for managing and routing the interactions between different strategies and the various components of the system, such as farming contracts, liquidity pools, and exchange plugins. By importing the StrategyRouter contract, you ensure that their strategies are compatible with the overall system architecture and can be seamlessly integrated into the platform.

Smart Contract Structure:

Every strategy smart contract should have the following functions:

  • depositToken: This view function returns the address of the token that the strategy accepts for deposit.

  • deposit: This function should handle the deposit of tokens into the strategy. It should take the necessary parameters, such as the amount of tokens to deposit, and update the relevant state variables.

  • withdraw: This function should allow the withdrawal of a specified amount of tokens from the strategy. It should take the necessary parameters, such as the amount of tokens to withdraw, and update the relevant state variables.

  • withdrawAll: This function should allow the withdrawal of all tokens from the strategy. It should update the relevant state variables and ensure that the token balances are correctly updated.

  • totalTokens: This function should return the total amount of tokens managed by the strategy.

  • compound: This function should reinvest the accrued rewards earned by the strategy back into the underlying asset, thus increasing the overall value of the strategy. This function should perform the following tasks:

    1. Claim any pending rewards from the relevant farming contract or liquidity pool.

    2. Convert the rewards into the underlying asset, either by swapping tokens on our exchange plugin.

    3. Deposit the converted rewards back into the farming contract or liquidity pool to increase the strategy's position and potential future rewards.

Testing Strategy Smart Contracts:

Tests should be comprehensive and cover all essential aspects of the strategy smart contract, including:

  • Token: depositToken function: Verify that the function returns the correct token address as expected.

  • Depositing tokens: Test that the deposit function works correctly by checking the token balances and state variables before and after the deposit.

  • Withdrawing tokens: Test the withdraw function by simulating various withdrawal scenarios (e.g., partial withdrawal, full withdrawal, etc.) and checking the token balances and state variables before and after the withdrawal.

  • Withdrawing all tokens: Test the withdrawAll function by simulating various scenarios (e.g., with and without pending rewards, etc.) and checking the token balances and state variables before and after the withdrawal.

  • Compounding tokens: Test the compound function, and ensure that the compound function correctly claims the pending rewards from the farming contract. Verify that the function successfully converts the claimed rewards into the underlying asset. Confirm that the function deposits the converted rewards back into the farming contract or liquidity pool. Ensure that the compound function handles edge cases and error conditions correctly, such as when there are no pending rewards to claim, when the conversion rate is unfavorable, or when the liquidity pool has insufficient liquidity to support the conversion.

Code Quality and Maintainability:

Ensure the code is clean, well-structured, and adheres to best practices. This includes:

  • Using clear and descriptive variable and function names.

  • Writing modular and reusable code, including the use of libraries and helper functions where appropriate.

  • Documenting the code with comments to explain the purpose and functionality of each function and any complex logic.

  • Adhering to the Solidity style guide and best practices, such as proper function visibility, error handling, and gas optimization.

Last updated