SmartChef-to-BNBRewardApe

Created Diff never expires
53 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
187 lines
99 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
234 lines
pragma solidity 0.6.12;
pragma solidity 0.6.12;


/*
* ApeSwapFinance
* App: https://apeswap.finance
* Medium: https://medium.com/@ape_swap
* Twitter: https://twitter.com/ape_swap
* Telegram: https://t.me/ape_swap
* Announcements: https://t.me/ape_swap_news
* GitHub: https://github.com/ApeSwapFinance
*/

import '@pancakeswap/pancake-swap-lib/contracts/math/SafeMath.sol';
import '@pancakeswap/pancake-swap-lib/contracts/math/SafeMath.sol';
import '@pancakeswap/pancake-swap-lib/contracts/token/BEP20/IBEP20.sol';
import '@pancakeswap/pancake-swap-lib/contracts/token/BEP20/IBEP20.sol';
import '@pancakeswap/pancake-swap-lib/contracts/token/BEP20/SafeBEP20.sol';
import '@pancakeswap/pancake-swap-lib/contracts/token/BEP20/SafeBEP20.sol';
import '@pancakeswap/pancake-swap-lib/contracts/access/Ownable.sol';
import '@pancakeswap/pancake-swap-lib/contracts/access/Ownable.sol';


// import "@nomiclabs/buidler/console.sol";



contract SmartChef is Ownable {
contract BNBRewardApe is Ownable {
using SafeMath for uint256;
using SafeMath for uint256;
using SafeBEP20 for IBEP20;
using SafeBEP20 for IBEP20;


// Info of each user.
// Info of each user.
struct UserInfo {
struct UserInfo {
uint256 amount; // How many LP tokens the user has provided.
uint256 amount; // How many LP tokens the user has provided.
uint256 rewardDebt; // Reward debt. See explanation below.
uint256 rewardDebt; // Reward debt. See explanation below.
}
}


// Info of each pool.
// Info of each pool.
struct PoolInfo {
struct PoolInfo {
IBEP20 lpToken; // Address of LP token contract.
IBEP20 lpToken; // Address of LP token contract.
uint256 allocPoint; // How many allocation points assigned to this pool. CAKEs to distribute per block.
uint256 allocPoint; // How many allocation points assigned to this pool. Rewards to distribute per block.
uint256 lastRewardBlock; // Last block number that CAKEs distribution occurs.
uint256 lastRewardBlock; // Last block number that Rewards distribution occurs.
uint256 accCakePerShare; // Accumulated CAKEs per share, times 1e12. See below.
uint256 accRewardTokenPerShare; // Accumulated Rewards per share, times 1e12. See below.
}
}


// The CAKE TOKEN!
// The stake TOKEN!
IBEP20 public syrup;
IBEP20 public stakeToken;
IBEP20 public rewardToken;


// CAKE tokens created per block.
// Reward tokens created per block.
uint256 public rewardPerBlock;
uint256 public rewardPerBlock;



// Info of each pool.
// Info of each pool.
PoolInfo[] public poolInfo;
PoolInfo[] public poolInfo;
// Info of each user that stakes LP tokens.
// Info of each user that stakes LP tokens.
mapping (address => UserInfo) public userInfo;
mapping (address => UserInfo) public userInfo;
// Total allocation poitns. Must be the sum of all allocation points in all pools.
// Total allocation poitns. Must be the sum of all allocation points in all pools.
uint256 private totalAllocPoint = 0;
uint256 private totalAllocPoint = 0;
// The block number when CAKE mining starts.
// The block number when Reward mining starts.
uint256 public startBlock;
uint256 public startBlock;
// The block number when CAKE mining ends.
// The block number when mining ends.
uint256 public bonusEndBlock;
uint256 public bonusEndBlock;


event Deposit(address indexed user, uint256 amount);
event Deposit(address indexed user, uint256 amount);
event DepositBNBRewards(uint256 amount);
event Withdraw(address indexed user, uint256 amount);
event Withdraw(address indexed user, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 amount);
event EmergencyRewardWithdraw(address indexed user, uint256 amount);


constructor(
constructor(
IBEP20 _syrup,
IBEP20 _stakeToken,
IBEP20 _rewardToken,
uint256 _rewardPerBlock,
uint256 _rewardPerBlock,
uint256 _startBlock,
uint256 _startBlock,
uint256 _bonusEndBlock
uint256 _bonusEndBlock
) public {
) public {
syrup = _syrup;
stakeToken = _stakeToken;
rewardToken = _rewardToken;
rewardPerBlock = _rewardPerBlock;
rewardPerBlock = _rewardPerBlock;
startBlock = _startBlock;
startBlock = _startBlock;
bonusEndBlock = _bonusEndBlock;
bonusEndBlock = _bonusEndBlock;


// staking pool
// staking pool
poolInfo.push(PoolInfo({
poolInfo.push(PoolInfo({
lpToken: _syrup,
lpToken: _stakeToken,
allocPoint: 1000,
allocPoint: 1000,
lastRewardBlock: startBlock,
lastRewardBlock: startBlock,
accCakePerShare: 0
accRewardTokenPerShare: 0
}));
}));


totalAllocPoint = 1000;
totalAllocPoint = 1000;


}
}


function stopReward() public onlyOwner {
bonusEndBlock = block.number;
}


// Return reward multiplier over the given _from to _to block.
// Return reward multiplier over the given _from to _to block.
function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) {
function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) {
if (_to <= bonusEndBlock) {
if (_to <= bonusEndBlock) {
return _to.sub(_from);
return _to.sub(_from);
} else if (_from >= bonusEndBlock) {
} else if (_from >= bonusEndBlock) {
return 0;
return 0;
} else {
} else {
return bonusEndBlock.sub(_from);
return bonusEndBlock.sub(_from);
}
}
}
}


// View function to see pending Reward on frontend.
// View function to see pending Reward on frontend.
function pendingReward(address _user) external view returns (uint256) {
function pendingReward(address _user) external view returns (uint256) {
PoolInfo storage pool = poolInfo[0];
PoolInfo storage pool = poolInfo[0];
UserInfo storage user = userInfo[_user];
UserInfo storage user = userInfo[_user];
uint256 accCakePerShare = pool.accCakePerShare;
uint256 accRewardTokenPerShare = pool.accRewardTokenPerShare;
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (block.number > pool.lastRewardBlock && lpSupply != 0) {
if (block.number > pool.lastRewardBlock && lpSupply != 0) {
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 cakeReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
accCakePerShare = accCakePerShare.add(cakeReward.mul(1e12).div(lpSupply));
accRewardTokenPerShare = accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply));
}
}
return user.amount.mul(accCakePerShare).div(1e12).sub(user.rewardDebt);
return user.amount.mul(accRewardTokenPerShare).div(1e12).sub(user.rewardDebt);
}
}


// Update reward variables of the given pool to be up-to-date.
// Update reward variables of the given pool to be up-to-date.
function updatePool(uint256 _pid) public {
function updatePool(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
if (block.number <= pool.lastRewardBlock) {
if (block.number <= pool.lastRewardBlock) {
return;
return;
}
}
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (lpSupply == 0) {
if (lpSupply == 0) {
pool.lastRewardBlock = block.number;
pool.lastRewardBlock = block.number;
return;
return;
}
}
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 cakeReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
pool.accCakePerShare = pool.accCakePerShare.add(cakeReward.mul(1e12).div(lpSupply));
pool.accRewardTokenPerShare = pool.accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply));
pool.lastRewardBlock = block.number;
pool.lastRewardBlock = block.number;
}
}


// Update reward variables for all pools. Be careful of gas spending!
// Update reward variables for all pools. Be careful of gas spending!
function massUpdatePools() public {
function massUpdatePools() public {
uint256 length = poolInfo.length;
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid);
updatePool(pid);
}
}
}
}




// Stake SYRUP tokens to SmartChef
/// Deposit staking token into the contract to earn rewards.
/// @dev Since this contract needs to be supplied with rewards we are
/// sending the balance of the contract if the pending rewards are higher
/// @param _amount The amount of staking tokens to deposit
function deposit(uint256 _amount) public {
function deposit(uint256 _amount) public {
PoolInfo storage pool = poolInfo[0];
PoolInfo storage pool = poolInfo[0];
UserInfo storage user = userInfo[msg.sender];
UserInfo storage user = userInfo[msg.sender];
updatePool(0);
updatePool(0);
if (user.amount > 0) {
if (user.amount > 0) {
uint256 pending = user.amount.mul(pool.accCakePerShare).div(1e12).sub(user.rewardDebt);
//
uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
rewardToken.safeTransfer(address(msg.sender), pending);
uint256 currentRewardBalance = rewardBalance();
if(currentRewardBalance > 0) {
if(pending > currentRewardBalance) {
safeTransferBNB(address(msg.sender), currentRewardBalance);
} else {
safeTransferBNB(address(msg.sender), pending);
}
}
}
}
}
}
if(_amount > 0) {
if(_amount > 0) {
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
user.amount = user.amount.add(_amount);
user.amount = user.amount.add(_amount);
}
}
user.rewardDebt = user.amount.mul(pool.accCakePerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.accRewardTokenPerShare).div(1e12);


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


// Withdraw SYRUP tokens from STAKING.
/// Withdraw rewards and/or staked tokens. Pass a 0 amount to withdraw only rewards
/// @param _amount The amount of staking tokens to withdraw
function withdraw(uint256 _amount) public {
function withdraw(uint256 _amount) public {
PoolInfo storage pool = poolInfo[0];
PoolInfo storage pool = poolInfo[0];
UserInfo storage user = userInfo[msg.sender];
UserInfo storage user = userInfo[msg.sender];
require(user.amount >= _amount, "withdraw: not good");
require(user.amount >= _amount, "withdraw: not good");
updatePool(0);
updatePool(0);
uint256 pending = user.amount.mul(pool.accCakePerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
rewardToken.safeTransfer(address(msg.sender), pending);
uint256 currentRewardBalance = rewardBalance();
if(currentRewardBalance > 0) {
if(pending > currentRewardBalance) {
safeTransferBNB(address(msg.sender), currentRewardBalance);
} else {
safeTransferBNB(address(msg.sender), pending);
}
}
}
}
if(_amount > 0) {
if(_amount > 0) {
user.amount = user.amount.sub(_amount);
user.amount = user.amount.sub(_amount);
pool.lpToken.safeTransfer(address(msg.sender), _amount);
pool.lpToken.safeTransfer(address(msg.sender), _amount);
}
}
user.rewardDebt = user.amount.mul(pool.accCakePerShare).div(1e12);

user.rewardDebt = user.amount.mul(pool.accRewardTokenPerShare).div(1e12);


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


/// Obtain the reward balance of this contract
/// @return wei balace of conract
function rewardBalance() public view returns (uint256) {
return payable(address(this)).balance;
}

// Deposit Rewards into contract
function depositBNBRewards() external payable {
require(msg.value > 0, 'Message has no BNB value to deposit into contract.');
emit DepositBNBRewards(msg.value);
}

/// @param to address to send BNB to
/// @param value wei value of BNB to transfer
function safeTransferBNB(address to, uint256 value) internal {
// Transfer BNB to address
(bool success, ) = to.call{gas: 23000, value: value}("");
require(success, 'TransferHelper: BNB_TRANSFER_FAILED');
}

/* Emergency Functions */

// Withdraw without caring about rewards. EMERGENCY ONLY.
// Withdraw without caring about rewards. EMERGENCY ONLY.
function emergencyWithdraw() public {
function emergencyWithdraw() external {
PoolInfo storage pool = poolInfo[0];
PoolInfo storage pool = poolInfo[0];
UserInfo storage user = userInfo[msg.sender];
UserInfo storage user = userInfo[msg.sender];
pool.lpToken.safeTransfer(address(msg.sender), user.amount);
pool.lpToken.safeTransfer(address(msg.sender), user.amount);
user.amount = 0;
user.amount = 0;
user.rewardDebt = 0;
user.rewardDebt = 0;
emit EmergencyWithdraw(msg.sender, user.amount);
emit EmergencyWithdraw(msg.sender, user.amount);
}
}


// Withdraw reward. EMERGENCY ONLY.
// Withdraw reward. EMERGENCY ONLY.
function emergencyRewardWithdraw(uint256 _amount) public onlyOwner {
function emergencyRewardWithdraw(uint256 _amount) external onlyOwner {
require(_amount < rewardToken.balanceOf(address(this)), 'not enough token');
require(_amount <= rewardBalance(), 'not enough rewards');
rewardToken.safeTransfer(address(msg.sender), _amount);
// Withdraw the BNB rewards
safeTransferBNB(address(msg.sender), _amount);
emit EmergencyRewardWithdraw(msg.sender, _amount);
}
}


}
}