Diff
checker
텍스트
텍스트
이미지
문서
Excel
폴더
Legal
Enterprise
데스크톱
요금제
로그인
데스크톱 앱 다운로드
텍스트 비교
두 텍스트 파일의 차이점을 찾아보세요
도구
기록
실시간 편집
변경 없는 행 숨기기
줄바꿈 비활성화
레이아웃
나란히 보기
합쳐 보기
비교 단위
스마트
단어
글자
구문 강조
언어 선택
제외
텍스트 변환
첫 변경으로
수정
Diffchecker Desktop
가장 안전하게 Diffchecker를 사용하는 방법. 데스크톱 앱을 사용하면 비교 데이터가 외부로 전송되지 않습니다!
데스크톱 앱 받기
BEP20RewardApe-to-BEP20RewardApeV2
생성일
5년 전
비교 결과 만료 없음
초기화
내보내기
공유
설명
0 삭제
행
총
삭제
글자
총
삭제
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
236 행
복사
14 추가
행
총
추가
글자
총
추가
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
249 행
복사
pragma solidity 0.6.12;
pragma solidity 0.6.12;
/*
/*
* ApeSwapFinance
* ApeSwapFinance
* App: https://apeswap.finance
* App: https://apeswap.finance
* Medium: https://ape-swap.medium.com
* Medium: https://ape-swap.medium.com
* Twitter: https://twitter.com/ape_swap
* Twitter: https://twitter.com/ape_swap
* Telegram: https://t.me/ape_swap
* Telegram: https://t.me/ape_swap
* Announcements: https://t.me/ape_swap_news
* Announcements: https://t.me/ape_swap_news
* GitHub: https://github.com/ApeSwapFinance
* 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';
복사
복사됨
복사
복사됨
contract BEP20RewardApe
is Ownable {
contract BEP20RewardApe
V2
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. Rewards 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 Rewards distribution occurs.
uint256 lastRewardBlock; // Last block number that Rewards distribution occurs.
uint256 accRewardTokenPerShare; // Accumulated Rewards per share, times 1e12. See below.
uint256 accRewardTokenPerShare; // Accumulated Rewards per share, times 1e12. See below.
}
}
// The stake token
// The stake token
IBEP20 public stakeToken;
IBEP20 public stakeToken;
// The reward token
// The reward token
IBEP20 public rewardToken;
IBEP20 public rewardToken;
// Reward 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 Reward mining starts.
// The block number when Reward mining starts.
uint256 public startBlock;
uint256 public startBlock;
// The block number when 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 DepositRewards(uint256 amount);
event DepositRewards(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);
event EmergencyRewardWithdraw(address indexed user, uint256 amount);
constructor(
constructor(
IBEP20 _stakeToken,
IBEP20 _stakeToken,
IBEP20 _rewardToken,
IBEP20 _rewardToken,
uint256 _rewardPerBlock,
uint256 _rewardPerBlock,
uint256 _startBlock,
uint256 _startBlock,
uint256 _bonusEndBlock
uint256 _bonusEndBlock
) public {
) public {
stakeToken = _stakeToken;
stakeToken = _stakeToken;
rewardToken = _rewardToken;
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: _stakeToken,
lpToken: _stakeToken,
allocPoint: 1000,
allocPoint: 1000,
lastRewardBlock: startBlock,
lastRewardBlock: startBlock,
accRewardTokenPerShare: 0
accRewardTokenPerShare: 0
}));
}));
totalAllocPoint = 1000;
totalAllocPoint = 1000;
}
}
// 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 accRewardTokenPerShare = pool.accRewardTokenPerShare;
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 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
accRewardTokenPerShare = accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply));
accRewardTokenPerShare = accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply));
}
}
return user.amount.mul(accRewardTokenPerShare).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 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
pool.accRewardTokenPerShare = pool.accRewardTokenPerShare.add(tokenReward.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);
}
}
}
}
/// Deposit staking token into the contract to earn rewards.
/// Deposit staking token into the contract to earn rewards.
/// @dev Since this contract needs to be supplied with rewards we are
/// @dev Since this contract needs to be supplied with rewards we are
/// sending the balance of the contract if the pending rewards are higher
/// sending the balance of the contract if the pending rewards are higher
/// @param _amount The amount of staking tokens to deposit
/// @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.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
uint256 currentRewardBalance = rewardBalance();
uint256 currentRewardBalance = rewardBalance();
if(currentRewardBalance > 0) {
if(currentRewardBalance > 0) {
if(pending > currentRewardBalance) {
if(pending > currentRewardBalance) {
safeTransferReward(address(msg.sender), currentRewardBalance);
safeTransferReward(address(msg.sender), currentRewardBalance);
} else {
} else {
safeTransferReward(address(msg.sender), pending);
safeTransferReward(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.accRewardTokenPerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.accRewardTokenPerShare).div(1e12);
emit Deposit(msg.sender, _amount);
emit Deposit(msg.sender, _amount);
}
}
/// Withdraw rewards and/or staked tokens. Pass a 0 amount to withdraw only rewards
/// Withdraw rewards and/or staked tokens. Pass a 0 amount to withdraw only rewards
/// @param _amount The amount of staking tokens to withdraw
/// @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.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
uint256 currentRewardBalance = rewardBalance();
uint256 currentRewardBalance = rewardBalance();
if(currentRewardBalance > 0) {
if(currentRewardBalance > 0) {
if(pending > currentRewardBalance) {
if(pending > currentRewardBalance) {
safeTransferReward(address(msg.sender), currentRewardBalance);
safeTransferReward(address(msg.sender), currentRewardBalance);
} else {
} else {
safeTransferReward(address(msg.sender), pending);
safeTransferReward(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.accRewardTokenPerShare).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
/// Obtain the reward balance of this contract
/// @return wei balace of conract
/// @return wei balace of conract
function rewardBalance() public view returns (uint256) {
function rewardBalance() public view returns (uint256) {
return rewardToken.balanceOf(address(this));
return rewardToken.balanceOf(address(this));
}
}
// Deposit Rewards into contract
// Deposit Rewards into contract
function depositRewards(uint256 _amount) external {
function depositRewards(uint256 _amount) external {
require(_amount > 0, 'Deposit value must be greater than 0.');
require(_amount > 0, 'Deposit value must be greater than 0.');
rewardToken.safeTransferFrom(address(msg.sender), address(this), _amount);
rewardToken.safeTransferFrom(address(msg.sender), address(this), _amount);
emit DepositRewards(_amount);
emit DepositRewards(_amount);
}
}
/// @param _to address to send reward token to
/// @param _to address to send reward token to
/// @param _amount value of reward token to transfer
/// @param _amount value of reward token to transfer
function safeTransferReward(address _to, uint256 _amount) internal {
function safeTransferReward(address _to, uint256 _amount) internal {
rewardToken.safeTransfer(_to, _amount);
rewardToken.safeTransfer(_to, _amount);
}
}
복사
복사됨
복사
복사됨
/* Admin Functions */
/// @param _rewardPerBlock The amount of reward tokens to be given per block
function setRewardPerBlock(uint256 _rewardPerBlock) external onlyOwner {
rewardPerBlock = _rewardPerBlock;
}
/// @param _bonusEndBlock The block when rewards will end
function setBonusEndBlock(uint256 _bonusEndBlock) external onlyOwner {
require(_bonusEndBlock > bonusEndBlock, 'new bonus end block must be greater than current');
bonusEndBlock = _bonusEndBlock;
}
/* Emergency Functions */
/* Emergency Functions */
// Withdraw without caring about rewards. EMERGENCY ONLY.
// Withdraw without caring about rewards. EMERGENCY ONLY.
function emergencyWithdraw() external {
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) external onlyOwner {
function emergencyRewardWithdraw(uint256 _amount) external onlyOwner {
require(_amount <= rewardBalance(), 'not enough rewards');
require(_amount <= rewardBalance(), 'not enough rewards');
// Withdraw rewards
// Withdraw rewards
safeTransferReward(address(msg.sender), _amount);
safeTransferReward(address(msg.sender), _amount);
emit EmergencyRewardWithdraw(msg.sender, _amount);
emit EmergencyRewardWithdraw(msg.sender, _amount);
}
}
}
}
저장된 비교 결과
원본
파일 열기
pragma solidity 0.6.12; /* * ApeSwapFinance * App: https://apeswap.finance * Medium: https://ape-swap.medium.com * 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/token/BEP20/IBEP20.sol'; import '@pancakeswap/pancake-swap-lib/contracts/token/BEP20/SafeBEP20.sol'; import '@pancakeswap/pancake-swap-lib/contracts/access/Ownable.sol'; contract BEP20RewardApe is Ownable { using SafeMath for uint256; using SafeBEP20 for IBEP20; // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. } // Info of each pool. struct PoolInfo { IBEP20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. Rewards to distribute per block. uint256 lastRewardBlock; // Last block number that Rewards distribution occurs. uint256 accRewardTokenPerShare; // Accumulated Rewards per share, times 1e12. See below. } // The stake token IBEP20 public stakeToken; // The reward token IBEP20 public rewardToken; // Reward tokens created per block. uint256 public rewardPerBlock; // Info of each pool. PoolInfo[] public poolInfo; // Info of each user that stakes LP tokens. mapping (address => UserInfo) public userInfo; // Total allocation poitns. Must be the sum of all allocation points in all pools. uint256 private totalAllocPoint = 0; // The block number when Reward mining starts. uint256 public startBlock; // The block number when mining ends. uint256 public bonusEndBlock; event Deposit(address indexed user, uint256 amount); event DepositRewards(uint256 amount); event Withdraw(address indexed user, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 amount); event EmergencyRewardWithdraw(address indexed user, uint256 amount); constructor( IBEP20 _stakeToken, IBEP20 _rewardToken, uint256 _rewardPerBlock, uint256 _startBlock, uint256 _bonusEndBlock ) public { stakeToken = _stakeToken; rewardToken = _rewardToken; rewardPerBlock = _rewardPerBlock; startBlock = _startBlock; bonusEndBlock = _bonusEndBlock; // staking pool poolInfo.push(PoolInfo({ lpToken: _stakeToken, allocPoint: 1000, lastRewardBlock: startBlock, accRewardTokenPerShare: 0 })); totalAllocPoint = 1000; } // Return reward multiplier over the given _from to _to block. function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { if (_to <= bonusEndBlock) { return _to.sub(_from); } else if (_from >= bonusEndBlock) { return 0; } else { return bonusEndBlock.sub(_from); } } // View function to see pending Reward on frontend. function pendingReward(address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[_user]; uint256 accRewardTokenPerShare = pool.accRewardTokenPerShare; uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (block.number > pool.lastRewardBlock && lpSupply != 0) { uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint); accRewardTokenPerShare = accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply)); } return user.amount.mul(accRewardTokenPerShare).div(1e12).sub(user.rewardDebt); } // Update reward variables of the given pool to be up-to-date. function updatePool(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; if (block.number <= pool.lastRewardBlock) { return; } uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (lpSupply == 0) { pool.lastRewardBlock = block.number; return; } uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint); pool.accRewardTokenPerShare = pool.accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply)); pool.lastRewardBlock = block.number; } // Update reward variables for all pools. Be careful of gas spending! function massUpdatePools() public { uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { updatePool(pid); } } /// 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 { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; updatePool(0); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { uint256 currentRewardBalance = rewardBalance(); if(currentRewardBalance > 0) { if(pending > currentRewardBalance) { safeTransferReward(address(msg.sender), currentRewardBalance); } else { safeTransferReward(address(msg.sender), pending); } } } } if(_amount > 0) { pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); user.amount = user.amount.add(_amount); } user.rewardDebt = user.amount.mul(pool.accRewardTokenPerShare).div(1e12); emit Deposit(msg.sender, _amount); } /// 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 { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(0); uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { uint256 currentRewardBalance = rewardBalance(); if(currentRewardBalance > 0) { if(pending > currentRewardBalance) { safeTransferReward(address(msg.sender), currentRewardBalance); } else { safeTransferReward(address(msg.sender), pending); } } } if(_amount > 0) { user.amount = user.amount.sub(_amount); pool.lpToken.safeTransfer(address(msg.sender), _amount); } user.rewardDebt = user.amount.mul(pool.accRewardTokenPerShare).div(1e12); emit Withdraw(msg.sender, _amount); } /// Obtain the reward balance of this contract /// @return wei balace of conract function rewardBalance() public view returns (uint256) { return rewardToken.balanceOf(address(this)); } // Deposit Rewards into contract function depositRewards(uint256 _amount) external { require(_amount > 0, 'Deposit value must be greater than 0.'); rewardToken.safeTransferFrom(address(msg.sender), address(this), _amount); emit DepositRewards(_amount); } /// @param _to address to send reward token to /// @param _amount value of reward token to transfer function safeTransferReward(address _to, uint256 _amount) internal { rewardToken.safeTransfer(_to, _amount); } /* Emergency Functions */ // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw() external { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; pool.lpToken.safeTransfer(address(msg.sender), user.amount); user.amount = 0; user.rewardDebt = 0; emit EmergencyWithdraw(msg.sender, user.amount); } // Withdraw reward. EMERGENCY ONLY. function emergencyRewardWithdraw(uint256 _amount) external onlyOwner { require(_amount <= rewardBalance(), 'not enough rewards'); // Withdraw rewards safeTransferReward(address(msg.sender), _amount); emit EmergencyRewardWithdraw(msg.sender, _amount); } }
수정본
파일 열기
pragma solidity 0.6.12; /* * ApeSwapFinance * App: https://apeswap.finance * Medium: https://ape-swap.medium.com * 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/token/BEP20/IBEP20.sol'; import '@pancakeswap/pancake-swap-lib/contracts/token/BEP20/SafeBEP20.sol'; import '@pancakeswap/pancake-swap-lib/contracts/access/Ownable.sol'; contract BEP20RewardApeV2 is Ownable { using SafeMath for uint256; using SafeBEP20 for IBEP20; // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. } // Info of each pool. struct PoolInfo { IBEP20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. Rewards to distribute per block. uint256 lastRewardBlock; // Last block number that Rewards distribution occurs. uint256 accRewardTokenPerShare; // Accumulated Rewards per share, times 1e12. See below. } // The stake token IBEP20 public stakeToken; // The reward token IBEP20 public rewardToken; // Reward tokens created per block. uint256 public rewardPerBlock; // Info of each pool. PoolInfo[] public poolInfo; // Info of each user that stakes LP tokens. mapping (address => UserInfo) public userInfo; // Total allocation poitns. Must be the sum of all allocation points in all pools. uint256 private totalAllocPoint = 0; // The block number when Reward mining starts. uint256 public startBlock; // The block number when mining ends. uint256 public bonusEndBlock; event Deposit(address indexed user, uint256 amount); event DepositRewards(uint256 amount); event Withdraw(address indexed user, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 amount); event EmergencyRewardWithdraw(address indexed user, uint256 amount); constructor( IBEP20 _stakeToken, IBEP20 _rewardToken, uint256 _rewardPerBlock, uint256 _startBlock, uint256 _bonusEndBlock ) public { stakeToken = _stakeToken; rewardToken = _rewardToken; rewardPerBlock = _rewardPerBlock; startBlock = _startBlock; bonusEndBlock = _bonusEndBlock; // staking pool poolInfo.push(PoolInfo({ lpToken: _stakeToken, allocPoint: 1000, lastRewardBlock: startBlock, accRewardTokenPerShare: 0 })); totalAllocPoint = 1000; } // Return reward multiplier over the given _from to _to block. function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { if (_to <= bonusEndBlock) { return _to.sub(_from); } else if (_from >= bonusEndBlock) { return 0; } else { return bonusEndBlock.sub(_from); } } // View function to see pending Reward on frontend. function pendingReward(address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[_user]; uint256 accRewardTokenPerShare = pool.accRewardTokenPerShare; uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (block.number > pool.lastRewardBlock && lpSupply != 0) { uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint); accRewardTokenPerShare = accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply)); } return user.amount.mul(accRewardTokenPerShare).div(1e12).sub(user.rewardDebt); } // Update reward variables of the given pool to be up-to-date. function updatePool(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; if (block.number <= pool.lastRewardBlock) { return; } uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (lpSupply == 0) { pool.lastRewardBlock = block.number; return; } uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 tokenReward = multiplier.mul(rewardPerBlock).mul(pool.allocPoint).div(totalAllocPoint); pool.accRewardTokenPerShare = pool.accRewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply)); pool.lastRewardBlock = block.number; } // Update reward variables for all pools. Be careful of gas spending! function massUpdatePools() public { uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { updatePool(pid); } } /// 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 { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; updatePool(0); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { uint256 currentRewardBalance = rewardBalance(); if(currentRewardBalance > 0) { if(pending > currentRewardBalance) { safeTransferReward(address(msg.sender), currentRewardBalance); } else { safeTransferReward(address(msg.sender), pending); } } } } if(_amount > 0) { pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); user.amount = user.amount.add(_amount); } user.rewardDebt = user.amount.mul(pool.accRewardTokenPerShare).div(1e12); emit Deposit(msg.sender, _amount); } /// 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 { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(0); uint256 pending = user.amount.mul(pool.accRewardTokenPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { uint256 currentRewardBalance = rewardBalance(); if(currentRewardBalance > 0) { if(pending > currentRewardBalance) { safeTransferReward(address(msg.sender), currentRewardBalance); } else { safeTransferReward(address(msg.sender), pending); } } } if(_amount > 0) { user.amount = user.amount.sub(_amount); pool.lpToken.safeTransfer(address(msg.sender), _amount); } user.rewardDebt = user.amount.mul(pool.accRewardTokenPerShare).div(1e12); emit Withdraw(msg.sender, _amount); } /// Obtain the reward balance of this contract /// @return wei balace of conract function rewardBalance() public view returns (uint256) { return rewardToken.balanceOf(address(this)); } // Deposit Rewards into contract function depositRewards(uint256 _amount) external { require(_amount > 0, 'Deposit value must be greater than 0.'); rewardToken.safeTransferFrom(address(msg.sender), address(this), _amount); emit DepositRewards(_amount); } /// @param _to address to send reward token to /// @param _amount value of reward token to transfer function safeTransferReward(address _to, uint256 _amount) internal { rewardToken.safeTransfer(_to, _amount); } /* Admin Functions */ /// @param _rewardPerBlock The amount of reward tokens to be given per block function setRewardPerBlock(uint256 _rewardPerBlock) external onlyOwner { rewardPerBlock = _rewardPerBlock; } /// @param _bonusEndBlock The block when rewards will end function setBonusEndBlock(uint256 _bonusEndBlock) external onlyOwner { require(_bonusEndBlock > bonusEndBlock, 'new bonus end block must be greater than current'); bonusEndBlock = _bonusEndBlock; } /* Emergency Functions */ // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw() external { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; pool.lpToken.safeTransfer(address(msg.sender), user.amount); user.amount = 0; user.rewardDebt = 0; emit EmergencyWithdraw(msg.sender, user.amount); } // Withdraw reward. EMERGENCY ONLY. function emergencyRewardWithdraw(uint256 _amount) external onlyOwner { require(_amount <= rewardBalance(), 'not enough rewards'); // Withdraw rewards safeTransferReward(address(msg.sender), _amount); emit EmergencyRewardWithdraw(msg.sender, _amount); } }
비교하기