How to Create a Yield Farming Contract

Yield farming, also known as liquidity mining, is a popular method in decentralized finance (DeFi) where users can earn rewards by staking their cryptocurrency assets in a liquidity pool. This article will explain the concept of yield farming and provide an example of a simple yield farming smart contract. If you are looking to develop your DeFi project, explore our DeFi development services.

How Yield Farming Works

In yield farming, users deposit their crypto assets into a DeFi protocol’s smart contract, known as a liquidity pool. These assets are then utilized by the protocol for various operations such as lending, borrowing, or trading. In exchange, the protocol rewards users with interest or additional cryptocurrency tokens.

Components of a Yield Farming Contract

A basic yield farming contract typically includes:

Liquidity Pool: Where users deposit their assets.

Reward Distribution: Reward concept to distribute rewards to users.

Staking Mechanism: Method used to stake allowed tokens.

Unstaking Mechanism: Allows users to withdraw their staked tokens and any earned rewards.

Sample Yield Farming Contract

Below is a simple example of a yield farming contract written in Solidity, a widely used programming language for creating Ethereum smart contracts.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
    function transferFrom(address senderAddress, address recipientAddress, uint256 value) external returns (bool);
    function transfer(address recipientAddress, uint256 value) external returns (bool);
}contract YieldFarm {
    IERC20 public stakingToken;
    IERC20 public rewardToken;    mapping(address => uint256) public stakedBalance;
    mapping(address => uint256) public rewards;
    uint256 public totalStaked;
    uint256 public rewardRate;    event Staked(address indexed user, uint256 amount);
    event Unstaked(address indexed user, uint256 amount);
    event RewardClaimed(address indexed user, uint256 amount);    constructor(IERC20 _stakingTokenAddress, IERC20 _rewardTokenAddress, uint256 _rewardRateValue) {
        stakingToken = _stakingTokenAddress;
        rewardToken = _rewardTokenAddress;
        rewardRate = _rewardRateValue;
    }    function stake(uint256 amount) external {
        require(amount > 0, 'Amount can not be zero');
        stakingToken.transferFrom(msg.sender, address(this), amount);
        stakedBalance[msg.sender] += amount;
        totalStaked += amount;
        emit Staked(msg.sender, amount);
    }    function unstake(uint256 amount) external {
        require(stakedBalance[msg.sender] >= amount, 'Insufficient staked balance');
        stakingToken.transfer(msg.sender, amount);
        stakedBalance[msg.sender] -= amount;
        totalStaked -= amount;
        emit Unstaked(msg.sender, amount);
    }    function claimRewards() external {
        uint256 reward = calculateRewardTokens(msg.sender);
        rewards[msg.sender] = 0;
        rewardToken.transfer(msg.sender, reward);
        emit RewardClaimed(msg.sender, reward);
    }    function calculateRewardTokens(address userAddress) public view returns (uint256) {
        return stakedBalance[user] * rewardRate;
    }
}

Testing the Contract

To test this contract, set up a development environment using tools like Hardhat. Here’s a basic test script:

const { expect } = require('chai');
describe('YieldFarm', function () {
  let stakingToken, rewardToken, yieldFarm;
  let ownerAddress, user1, user2;  beforeEach(async function () {
    [ownerAddress, user1, user2, _] = await ethers.getSigners();    const Token = await ethers.getContractFactory('Token');
    stakingToken = await Token.deploy('Staking Token', 'STK', 1000000);
    rewardToken = await Token.deploy('Reward Token', 'RWD', 1000000);    const YieldFarm = await ethers.getContractFactory('YieldFarm');
    yieldFarm = await YieldFarm.deploy(stakingToken.address, rewardToken.address, 1);    await stakingToken.transfer(user1.address, 1000);
    await stakingToken.transfer(user2.address, 1000);
    await rewardToken.transfer(yieldFarm.address, 1000);
  });  it('Stake and earn', async function () {
    await stakingToken.connect(user1).approve(yieldFarm.address, 100);
    await yieldFarm.connect(user1).stake(100);
    expect(await stakingToken.balanceOf(user1.address)).to.equal(900);
    expect(await stakingToken.balanceOf(yieldFarm.address)).to.equal(100);    await yieldFarm.connect(user1).claimRewards();
    expect(await rewardToken.balanceOf(user1.address)).to.equal(100);
  });  it('Should allow users to unstake tokens', async function () {
    await stakingToken.connect(user1).approve(yieldFarm.address, 100);
    await yieldFarm.connect(user1).stake(100);    await yieldFarm.connect(user1).unstake(100);
    expect(await stakingToken.balanceOf(user1.address)).to.equal(1000);
  });
});

Conclusion

Yield farming is a fundamental aspect of DeFi, enabling users to earn rewards by providing liquidity to protocols. The provided contract is a simplified example to illustrate the core concepts. In real-world applications, additional security measures and optimizations are essential. If you are looking for more information about smart contracts for DeFi development, connect with our skilled blockchain developers.

0
Subscribe to my newsletter

Read articles from Mohd Arslan Siddiqui directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mohd Arslan Siddiqui
Mohd Arslan Siddiqui

Expert blockchain writer with a knack for simplicity. Blends technical depth with engaging storytelling.