//SPDX-License-Identifier: MIT pragma solidity ^0.7.0; pragma abicoder v2; import { TokenInterface } from "../../../common/interfaces.sol"; import { DSMath } from "../../../common/math.sol"; import { Basic } from "../../../common/basic.sol"; import { IERC20, IMiniChefV2, IStakingRewards } from "./interface.sol"; abstract contract Helpers is DSMath, Basic { /** * @dev Pangolin MiniChefV2 */ IMiniChefV2 internal constant minichefv2 = IMiniChefV2(0x1f806f7C8dED893fd3caE279191ad7Aa3798E928); /** * @dev Pangolin Token */ IERC20 internal constant PNG = IERC20(0x60781C2586D68229fde47564546784ab3fACA982); // LP Staking, use minichefv2 to staking lp tokens and earn png function _depositLPStake( uint pid, uint amount ) internal returns (address lpTokenAddr) { require(pid < minichefv2.poolLength(), "Invalid pid!"); IERC20 lptoken = minichefv2.lpToken(pid); require(amount > 0, "Invalid amount, amount cannot be 0"); require(lptoken.balanceOf(address(this)) > 0, "Invalid LP token balance"); require(lptoken.balanceOf(address(this)) >= amount, "Invalid amount, amount greater than balance of LP token"); approve( lptoken, address(minichefv2), amount ); minichefv2.deposit(pid, amount, address(this)); lpTokenAddr = address(lptoken); } function _withdraw_LP_Stake( uint pid, uint amount ) internal returns (address lpTokenAddr) { require(pid < minichefv2.poolLength(), "Invalid pid!"); IMiniChefV2.UserInfo memory userinfo = minichefv2.userInfo(pid, address(this)); require(userinfo.amount >= amount, "Invalid amount, amount greater than balance of staking"); require(amount > 0, "Invalid amount, amount cannot be 0"); minichefv2.withdraw(pid, amount, address(this)); IERC20 lptoken = minichefv2.lpToken(pid); lpTokenAddr = address(lptoken); } function _withdraw_and_getRewards_LP_Stake( uint pid, uint amount ) internal returns (uint256 rewardAmount, address lpTokenAddr) { require(pid < minichefv2.poolLength(), "Invalid pid!"); IMiniChefV2.UserInfo memory userinfo = minichefv2.userInfo(pid, address(this)); require(userinfo.amount >= amount, "Invalid amount, amount greater than balance of staking"); require(amount > 0, "Invalid amount, amount cannot be 0"); rewardAmount = minichefv2.pendingReward(pid, address(this)); minichefv2.withdrawAndHarvest(pid, amount, address(this)); IERC20 lptoken = minichefv2.lpToken(pid); lpTokenAddr = address(lptoken); } function _getLPStakeReward( uint pid ) internal returns (uint256 rewardAmount, address lpTokenAddr) { require(pid < minichefv2.poolLength(), "Invalid pid!"); rewardAmount = minichefv2.pendingReward(pid, address(this)); require(rewardAmount > 0, "No rewards to claim"); minichefv2.harvest(pid, address(this)); IERC20 lptoken = minichefv2.lpToken(pid); lpTokenAddr = address(lptoken); } function _emergencyWithdraw_LP_Stake( uint pid ) internal returns (uint256 lpAmount, address lpTokenAddr) { require(pid < minichefv2.poolLength(), "Invalid pid!"); IMiniChefV2.UserInfo memory userinfo = minichefv2.userInfo(pid, address(this)); lpAmount = userinfo.amount; minichefv2.emergencyWithdraw(pid, address(this)); IERC20 lptoken = minichefv2.lpToken(pid); lpTokenAddr = address(lptoken); } // PNG Staking (Stake PNG, earn another token) function _depositPNGStake( address stakingContract_addr, uint amount ) internal { IStakingRewards stakingContract = IStakingRewards(stakingContract_addr); require(amount > 0, "Invalid amount, amount cannot be 0"); require(PNG.balanceOf(address(this)) > 0, "Invalid PNG balance"); require(PNG.balanceOf(address(this)) >= amount, "Invalid amount, amount greater than balance of PNG"); approve(PNG, stakingContract_addr, amount); stakingContract.stake(amount); } function _withdrawPNGStake( address stakingContract_addr, uint amount ) internal { IStakingRewards stakingContract = IStakingRewards(stakingContract_addr); require(stakingContract.balanceOf(address(this)) >= amount, "Invalid amount, amount greater than balance of staking"); require(amount > 0, "Invalid amount, amount cannot be 0"); stakingContract.withdraw(amount); } function _exitPNGStake( address stakingContract_addr ) internal returns (uint256 exitAmount, uint256 rewardAmount, address rewardToken){ IStakingRewards stakingContract = IStakingRewards(stakingContract_addr); exitAmount = stakingContract.balanceOf(address(this)); rewardAmount = stakingContract.rewards(address(this)); require(exitAmount > 0, "No balance to exit"); stakingContract.exit(); } function _claimPNGStakeReward( address stakingContract_addr ) internal returns (uint256 rewardAmount, address rewardToken) { IStakingRewards stakingContract = IStakingRewards(stakingContract_addr); rewardAmount = stakingContract.rewards(address(this)); rewardToken = stakingContract.rewardsToken(); require(rewardAmount > 0, "No rewards to claim"); stakingContract.getReward(); } }