SmartChef-to-BNBRewardApe
53 removals
Words removed | 69 |
Total words | 629 |
Words removed (%) | 10.97 |
187 lines
99 additions
Words added | 278 |
Total words | 838 |
Words added (%) | 33.17 |
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);
}
}
}
}