Yield Farming

Farm LP tokens for additional yield.

Outlined below are the common operations associated with yield farming:

Contract ID: Masterchef

Query https://api.saucerswap.finance/farms/ for all eligible farm pool IDs.

Query https://api.saucerswap.finance/pools/ for all available pool IDs


Deposit LP Tokens to a Farm

Deposit any amount of LP tokens to an existing farm to earn additional yield.

Function name: deposit

Recommended gas: 210,000 gwei (~ $0.018 USD)

Parameter NameDescription

uint256 _pid

Liquidity pool id

uint256 _amount

LP token amount in its smallest unit

Solidity Function Body
//MasterChef.sol

function deposit(uint256 _pid, uint256 _amount) external payable nonReentrant {
  require(msg.value >= tinycentsToTinybars(depositFee), 'msg.value < depositFee');
  
  // send rent to rentPayer
  (bool result, ) = rentPayer.call{value: msg.value}("");
  if (!result) {
    emit DidNotReceiveHbar(rentPayer, msg.value);
  }
  
  UserInfo storage user = userInfo[_pid][msg.sender];    
  PoolInfo storage pool = poolInfo[_pid];

  updatePool(_pid);

  uint256 pending = (user.amount * pool.accSaucePerShare / 1e12) - user.rewardDebt;
  uint256 pendingHbar = (user.amount * pool.accHBARPerShare / 1e12) - user.rewardDebtHbar;

  user.amount = user.amount + _amount;
  user.rewardDebt = user.amount * pool.accSaucePerShare / 1e12;
  user.rewardDebtHbar = user.amount * pool.accHBARPerShare / 1e12;

  if(pending > 0) {
    safeSauceTransfer(msg.sender, pending);
  }
  
  if (_amount > 0) {
    safeTransferToken(pool.lpToken, msg.sender, address(this), _amount.toInt256().toInt64());
  }

  emit Deposit(msg.sender, _pid, _amount);

  if (pendingHbar > 0) {
    safeHBARTransfer(msg.sender, pendingHbar);
  }
}

A spender allowance for the Farm contract is required for the LP token.

It costs $0.25 USD, payable in HBAR, to deposit the tokens into a farm. To get the current deposit creation fee, call the depositFee() method from the Farm contract. This will will return the current value expressed in Tinycent. To accurately convert this value to Tinybar, query the exchange rate from /api/v1/network/exchangerate

Code Overview

Resources:

import { 
  ContractFunctionParameters, 
  ContractExecuteTransaction,
  AccountAllowanceApproveTransaction, 
  .. 
} from '@hashgraph/sdk';

//Client pre-checks:
// - Farm contract has spender allowance for the LP token

const params = new ContractFunctionParameters();
params.addUint256(poolId); //uint _pid
params.addUint256(lpTokenAmount); //uint _amount
    
await new ContractExecuteTransaction()
 .setPayableAmount(depositFeeInHbar)
 .setContractId(farmContractId)
 .setGas(gasLim)
 .setFunction('deposit', params)
 .execute(client);

Get User's Current Farm Reward

Get current HBAR and SAUCE yield reward values for a user

Function name: pendingSauce

No gas cost

Parameter NameDescription

uint256 _pid

Liquidity pool id

address _user

User's solidity address

Solidity Function Body
//MasterChef.sol

function pendingSauce(uint256 _pid, address _user) external view returns (uint256, uint256) {
  PoolInfo storage pool = poolInfo[_pid];
  UserInfo storage user = userInfo[_pid][_user];
  uint256 accSaucePerShare = pool.accSaucePerShare;
  uint256 accHBARPerShare = pool.accHBARPerShare;
  uint256 lpSupply = IERC20(pool.lpToken).balanceOf(address(this));
  if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {
    uint256 multiplier = getMultiplier(pool.lastRewardTime, block.timestamp);
    uint256 sauceReward = multiplier * (saucePerSecond) * (pool.allocPoint) / (totalAllocPoint);
    uint256 hbarReward = multiplier * (hbarPerSecond) * (pool.allocPoint) / (totalAllocPoint);
    accSaucePerShare = accSaucePerShare + (sauceReward * (1e12) / (lpSupply));
    accHBARPerShare = accHBARPerShare + (hbarReward * (1e12) / (lpSupply));
  }

  return (user.amount * (accSaucePerShare) / (1e12) - (user.rewardDebt), user.amount * (accHBARPerShare) / (1e12) - (user.rewardDebtHbar));
}

Code Overview

Resources:

import * as ethers from 'ethers'; //V6

//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
  batchMaxCount: 1, //workaround for V6
});

const interfaces = new ethers.Interface([
  'function pendingSauce(uint256 _pid, address _user) external view returns (uint256, uint256)'
]);

const farmContract = new ethers.Contract(farmEvmAddress, interfaces.fragments, provider);
const result = await farmContract.pendingSauce(poolId, userEvmAddress);
const pendingSauceTiny = result[0]; //uint256
const pendingTinybar = result[1]; //uint256

Withdraw LP Tokens from a Farm

Withdraw any amount of LP tokens from an existing farm.

Function name: withdraw

Recommended gas: 190,000 gwei (~ $0.016 USD)

Parameter NameDescription

uint256 _pid

Liquidity pool id

uint256 _amount

LP token amount in its smallest unit

Solidity Function Body
//MasterChef.sol

function withdraw(uint256 _pid, uint256 _amount) external nonReentrant {  
  PoolInfo storage pool = poolInfo[_pid];
  UserInfo storage user = userInfo[_pid][msg.sender];

  require(user.amount >= _amount, "withdraw: not good");
  updatePool(_pid);

  uint256 pending = (user.amount * pool.accSaucePerShare / 1e12) - user.rewardDebt;
  uint256 pendingHbar = (user.amount * pool.accHBARPerShare / 1e12) - user.rewardDebtHbar;

  user.amount = user.amount - _amount;
  user.rewardDebt = user.amount * pool.accSaucePerShare / 1e12;
  user.rewardDebtHbar = user.amount * pool.accHBARPerShare / 1e12;

  if(pending > 0) {
    safeSauceTransfer(msg.sender, pending);
  }
  
  if(_amount > 0) {
    safeTransferToken(address(pool.lpToken), address(this), msg.sender, _amount.toInt256().toInt64());
  }

  emit Withdraw(msg.sender, _pid, _amount);

  if (pendingHbar > 0) { 
    safeHBARTransfer(msg.sender, pendingHbar);
  }
}

Code Overview

Resources:

import { 
  ContractFunctionParameters, 
  ContractExecuteTransaction, 
  .. 
} from '@hashgraph/sdk';

const params = new ContractFunctionParameters();
params.addUint256(poolId); //uint _pid
params.addUint256(lpTokenAmount); //uint _amount
    
await new ContractExecuteTransaction()
 .setContractId(farmContractId)
 .setGas(gasLim)
 .setFunction('withdraw', params)
 .execute(client);

Last updated