Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
ライブエディター
未変更行を折りたたむ
折り返しなし
レイアウト
分割
統合
比較精度
スマート
単語
文字
シンタックスハイライト
構文を選択
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
MasterChef
作成日
5 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
142 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
332 行
すべてコピー
156 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
347 行
すべてコピー
コピー
コピー済み
コピー
コピー済み
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma solidity 0.6.12;
コピー
コピー済み
コピー
コピー済み
import
'@pancakeswap/pancake-swap-lib
/contracts/
math/SafeMath
.sol
'
;
import
"@openzeppelin
/contracts/
token/ERC20/IERC20
.sol
"
;
import
'@pancakeswap/pancake-swap-lib
/contracts/token/
BEP20/IBEP20
.sol
'
;
import
"@openzeppelin
/contracts/token/
ERC20/SafeERC20
.sol
"
;
import
'@pancakeswap/pancake-swap-lib
/contracts/
token/BEP20/SafeBEP20
.sol
'
;
import
"@openzeppelin
/contracts/
utils/EnumerableSet.sol";
import
'@pancakeswap/pancake-swap-lib
/contracts/access/Ownable.sol
';
import "@openzeppelin/contracts/math/SafeMath
.sol
"
;
import
"@openzeppelin
/contracts/access/Ownable.sol
";
import "./CakeToken.sol";
import "./SyrupBar.sol
";
コピー
コピー済み
コピー
コピー済み
//
import "
@nomiclabs/buidler/console
.sol";
import "
./FinToken.sol";
import "./CaviarBar
.sol";
interface IMigratorChef {
interface IMigratorChef {
コピー
コピー済み
コピー
コピー済み
// Perform LP token migration from legacy
PancakeSwap
to
CakeSwap
.
// Perform LP token migration from legacy
FinSwap
to
new FinSwap
.
// Take the current LP token address and return the new LP token address.
// Take the current LP token address and return the new LP token address.
// Migrator should have full access to the caller's LP token.
// Migrator should have full access to the caller's LP token.
// Return the new LP token address.
// Return the new LP token address.
//
//
コピー
コピー済み
コピー
コピー済み
// XXX Migrator must have allowance access to
PancakeSwap
LP tokens.
// XXX Migrator must have allowance access to
FinSwap
LP tokens.
//
CakeSwap
must mint EXACTLY the same amount of
CakeSwap
LP tokens or
//
FinSwap
must mint EXACTLY the same amount of
FinSwap
LP tokens or
// else something bad will happen. Traditional
PancakeSwap
does not
// else something bad will happen. Traditional
FinSwap
does not
// do that so be careful!
// do that so be careful!
コピー
コピー済み
コピー
コピー済み
function migrate(I
BEP
20 token) external returns (I
BEP
20);
function migrate(I
ERC
20 token) external returns (I
ERC
20);
}
}
コピー
コピー済み
コピー
コピー済み
// MasterChef is the master of
Cake
. He can make
Cake
and he is a fair guy.
// MasterChef is the master of
Fins
. He can make
Fins
and he is a fair guy.
//
//
// Note that it's ownable and the owner wields tremendous power. The ownership
// Note that it's ownable and the owner wields tremendous power. The ownership
コピー
コピー済み
コピー
コピー済み
// will be transferred to a governance smart contract once
CAKE
is sufficiently
// will be transferred to a governance smart contract once
FINS
is sufficiently
// distributed and the community can show to govern itself.
// distributed and the community can show to govern itself.
//
//
// Have fun reading it. Hopefully it's bug-free. God bless.
// Have fun reading it. Hopefully it's bug-free. God bless.
contract MasterChef is Ownable {
contract MasterChef is Ownable {
using SafeMath for uint256;
using SafeMath for uint256;
コピー
コピー済み
コピー
コピー済み
using Safe
BEP
20 for I
BEP
20;
using Safe
ERC
20 for I
ERC
20;
// 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.
//
//
コピー
コピー済み
コピー
コピー済み
// We do some fancy math here. Basically, any point in time, the amount of
CAKEs
// We do some fancy math here. Basically, any point in time, the amount of
FINSs
// entitled to a user but is pending to be distributed is:
// entitled to a user but is pending to be distributed is:
//
//
コピー
コピー済み
コピー
コピー済み
// pending reward = (user.amount * pool.acc
Cake
PerShare) - user.rewardDebt
// pending reward = (user.amount * pool.acc
Fins
PerShare) - user.rewardDebt
//
//
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:
コピー
コピー済み
コピー
コピー済み
// 1. The pool's `acc
Cake
PerShare` (and `lastReward
Block
`) gets updated.
// 1. The pool's `acc
Fins
PerShare` (and `lastReward
Time
`) gets updated.
// 2. User receives the pending reward sent to his/her address.
// 2. User receives the pending reward sent to his/her address.
// 3. User's `amount` gets updated.
// 3. User's `amount` gets updated.
// 4. User's `rewardDebt` gets updated.
// 4. User's `rewardDebt` gets updated.
}
}
// Info of each pool.
// Info of each pool.
struct PoolInfo {
struct PoolInfo {
コピー
コピー済み
コピー
コピー済み
I
BEP
20 lpToken; // Address of LP token contract.
I
ERC
20 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.
FINS
to distribute per block.
uint256 lastReward
Block
; // Last block number that
CAKEs
distribution occurs.
uint256 lastReward
Time
; // Last block number that
FINS
distribution occurs.
uint256 acc
Cake
PerShare; // Accumulated
CAKEs
per share, times 1e12. See below.
uint256 acc
Fins
PerShare; // Accumulated
FINS
per share, times 1e12. See below.
}
}
コピー
コピー済み
コピー
コピー済み
// The
CAKE
TOKEN!
// The
FINS
TOKEN!
CakeToken
public
cake
;
FinToken
public
fins
;
// The
SYRUP
TOKEN!
// The
caviar
TOKEN!
SyrupBar
public
syrup
;
CaviarBar
public
caviar
;
// Dev address.
// Dev address.
address public devaddr;
address public devaddr;
コピー
コピー済み
コピー
コピー済み
//
CAKE
tokens created per
block
.
//
FINS
tokens created per
second
.
uint256 public
cakePerBlock
;
uint256 public
finsPerSecond
;
//
Bonus muliplier for early cake makers.
//
Max finsPerSecond keep never ol
uint256 public
BONUS_MULTIPLIER
=
1;
uint256 public
constant maxFinsPerSecond
=
1e18;
// The migrator contract. It has a lot of power. Can only be set through governance (owner).
// The migrator contract. It has a lot of power. Can only be set through governance (owner).
IMigratorChef public migrator;
IMigratorChef public migrator;
// Info of each pool.
// Info of each pool.
PoolInfo[] public poolInfo;
PoolInfo[] public poolInfo;
コピー
コピー済み
コピー
コピー済み
// add the same LP token only once
mapping(address => bool) lpExists;
// Info of each user that stakes LP tokens.
// Info of each user that stakes LP tokens.
mapping (uint256 => mapping (address => UserInfo)) public userInfo;
mapping (uint256 => mapping (address => UserInfo)) public userInfo;
// Total allocation points. Must be the sum of all allocation points in all pools.
// Total allocation points. Must be the sum of all allocation points in all pools.
uint256 public totalAllocPoint = 0;
uint256 public totalAllocPoint = 0;
コピー
コピー済み
コピー
コピー済み
// The block number when
CAKE
mining starts.
// The block number when
FINS
mining starts.
uint256 public
startBlock
;
uint256 public
startTime
;
event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
constructor(
constructor(
コピー
コピー済み
コピー
コピー済み
CakeToken _cake
,
FinToken _fins
,
SyrupBar _syrup
,
CaviarBar _caviar
,
address _devaddr,
address _devaddr,
コピー
コピー済み
コピー
コピー済み
uint256 _
cakePerBlock
,
uint256 _
finsPerSecond
,
uint256 _
startBlock
uint256 _
startTime
) public {
) public {
コピー
コピー済み
コピー
コピー済み
cake
= _
cake
;
fins
= _
fins
;
syrup
= _
syrup
;
caviar
= _
caviar
;
devaddr = _devaddr;
devaddr = _devaddr;
コピー
コピー済み
コピー
コピー済み
cakePerBlock
= _
cakePerBlock
;
finsPerSecond
= _
finsPerSecond
;
startBlock
= _
startBlock
;
startTime
= _
startTime
;
// staking pool
// staking pool
poolInfo.push(PoolInfo({
poolInfo.push(PoolInfo({
コピー
コピー済み
コピー
コピー済み
lpToken: _
cake
,
lpToken: _
fins
,
allocPoint: 1000,
allocPoint: 1000,
コピー
コピー済み
コピー
コピー済み
lastReward
Block: startBlock
,
lastReward
Time: startTime
,
acc
Cake
PerShare: 0
acc
Fins
PerShare: 0
}));
}));
totalAllocPoint = 1000;
totalAllocPoint = 1000;
}
}
コピー
コピー済み
コピー
コピー済み
function updateMultiplier(uint256 multiplierNumber) public onlyOwner {
BONUS_MULTIPLIER = multiplierNumber;
}
function poolLength() external view returns (uint256) {
function poolLength() external view returns (uint256) {
return poolInfo.length;
return poolInfo.length;
}
}
// Add a new lp to the pool. Can only be called by the owner.
// Add a new lp to the pool. Can only be called by the owner.
// XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.
// XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.
コピー
コピー済み
コピー
コピー済み
function add(uint256 _allocPoint, I
BEP
20 _lpToken, bool _withUpdate) public onlyOwner {
function add(uint256 _allocPoint, I
ERC
20 _lpToken, bool _withUpdate) public onlyOwner {
require(!lpExists[address(_lpToken)], "!lpToken exists");
if (_withUpdate) {
if (_withUpdate) {
massUpdatePools();
massUpdatePools();
}
}
コピー
コピー済み
コピー
コピー済み
uint256 lastReward
Block
= block.
number
>
startBlock
? block.
number
:
startBlock
;
uint256 lastReward
Time
= block.
timestamp
>
startTime
? block.
timestamp
:
startTime
;
totalAllocPoint = totalAllocPoint.add(_allocPoint);
totalAllocPoint = totalAllocPoint.add(_allocPoint);
poolInfo.push(PoolInfo({
poolInfo.push(PoolInfo({
lpToken: _lpToken,
lpToken: _lpToken,
allocPoint: _allocPoint,
allocPoint: _allocPoint,
コピー
コピー済み
コピー
コピー済み
lastReward
Block
: lastReward
Block
,
lastReward
Time
: lastReward
Time
,
acc
Cake
PerShare: 0
acc
Fins
PerShare: 0
}));
}));
updateStakingPool();
updateStakingPool();
コピー
コピー済み
コピー
コピー済み
lpExists[address(_lpToken)] = true;
}
}
コピー
コピー済み
コピー
コピー済み
// Update the given pool's
CAKE
allocation point. Can only be called by the owner.
// Update the given pool's
FINS
allocation point. Can only be called by the owner.
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {
if (_withUpdate) {
if (_withUpdate) {
massUpdatePools();
massUpdatePools();
}
}
uint256 prevAllocPoint = poolInfo[_pid].allocPoint;
uint256 prevAllocPoint = poolInfo[_pid].allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
if (prevAllocPoint != _allocPoint) {
if (prevAllocPoint != _allocPoint) {
totalAllocPoint = totalAllocPoint.sub(prevAllocPoint).add(_allocPoint);
totalAllocPoint = totalAllocPoint.sub(prevAllocPoint).add(_allocPoint);
updateStakingPool();
updateStakingPool();
}
}
}
}
function updateStakingPool() internal {
function updateStakingPool() internal {
uint256 length = poolInfo.length;
uint256 length = poolInfo.length;
uint256 points = 0;
uint256 points = 0;
for (uint256 pid = 1; pid < length; ++pid) {
for (uint256 pid = 1; pid < length; ++pid) {
points = points.add(poolInfo[pid].allocPoint);
points = points.add(poolInfo[pid].allocPoint);
}
}
if (points != 0) {
if (points != 0) {
points = points.div(3);
points = points.div(3);
totalAllocPoint = totalAllocPoint.sub(poolInfo[0].allocPoint).add(points);
totalAllocPoint = totalAllocPoint.sub(poolInfo[0].allocPoint).add(points);
poolInfo[0].allocPoint = points;
poolInfo[0].allocPoint = points;
}
}
}
}
// Set the migrator contract. Can only be called by the owner.
// Set the migrator contract. Can only be called by the owner.
function setMigrator(IMigratorChef _migrator) public onlyOwner {
function setMigrator(IMigratorChef _migrator) public onlyOwner {
migrator = _migrator;
migrator = _migrator;
}
}
// Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good.
// Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good.
function migrate(uint256 _pid) public {
function migrate(uint256 _pid) public {
require(address(migrator) != address(0), "migrate: no migrator");
require(address(migrator) != address(0), "migrate: no migrator");
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
コピー
コピー済み
コピー
コピー済み
I
BEP
20 lpToken = pool.lpToken;
I
ERC
20 lpToken = pool.lpToken;
uint256 bal = lpToken.balanceOf(address(this));
uint256 bal = lpToken.balanceOf(address(this));
lpToken.safeApprove(address(migrator), bal);
lpToken.safeApprove(address(migrator), bal);
コピー
コピー済み
コピー
コピー済み
I
BEP
20 newLpToken = migrator.migrate(lpToken);
I
ERC
20 newLpToken = migrator.migrate(lpToken);
require(bal == newLpToken.balanceOf(address(this)), "migrate: bad");
require(bal == newLpToken.balanceOf(address(this)), "migrate: bad");
pool.lpToken = newLpToken;
pool.lpToken = newLpToken;
}
}
// 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) {
コピー
コピー済み
コピー
コピー済み
return _to.sub(_from)
.mul(BONUS_MULTIPLIER)
;
_from = _from > startTime ? _from : startTime;
if (_to < startTime) {
return 0;
}
return _to.sub(_from)
;
}
}
コピー
コピー済み
コピー
コピー済み
// View function to see pending
CAKEs
on frontend.
// View function to see pending
FINS
on frontend.
function
pendingCake
(uint256 _pid, address _user) external view returns (uint256) {
function
pendingFins
(uint256 _pid, address _user) external view returns (uint256) {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
UserInfo storage user = userInfo[_pid][_user];
コピー
コピー済み
コピー
コピー済み
uint256 acc
Cake
PerShare = pool.acc
Cake
PerShare;
uint256 acc
Fins
PerShare = pool.acc
Fins
PerShare;
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
コピー
コピー済み
コピー
コピー済み
if (block.
number
> pool.lastReward
Block
&& lpSupply != 0) {
if (block.
timestamp
> pool.lastReward
Time
&& lpSupply != 0) {
uint256 multiplier = getMultiplier(pool.lastReward
Block
, block.
number
);
uint256 multiplier = getMultiplier(pool.lastReward
Time
, block.
timestamp
);
uint256
cakeReward
= multiplier.mul(
cakePerBlock
).mul(pool.allocPoint).div(totalAllocPoint);
uint256
finsReward
= multiplier.mul(
finsPerSecond
).mul(pool.allocPoint).div(totalAllocPoint);
acc
Cake
PerShare = acc
Cake
PerShare.add(
cakeReward
.mul(1e12).div(lpSupply));
acc
Fins
PerShare = acc
Fins
PerShare.add(
finsReward
.mul(1e12).div(lpSupply));
}
}
コピー
コピー済み
コピー
コピー済み
return user.amount.mul(acc
Cake
PerShare).div(1e12).sub(user.rewardDebt);
return user.amount.mul(acc
Fins
PerShare).div(1e12).sub(user.rewardDebt);
}
}
// 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);
}
}
}
}
// 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.lastReward
Block
) {
if (block.
timestamp
<= pool.lastReward
Time
) {
return;
return;
}
}
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (lpSupply == 0) {
if (lpSupply == 0) {
コピー
コピー済み
コピー
コピー済み
pool.lastReward
Block
= block.
number
;
pool.lastReward
Time
= block.
timestamp
;
return;
return;
}
}
コピー
コピー済み
コピー
コピー済み
uint256 multiplier = getMultiplier(pool.lastReward
Block
, block.
number
);
uint256 multiplier = getMultiplier(pool.lastReward
Time
, block.
timestamp
);
uint256
cakeReward
= multiplier.mul(
cakePerBlock
).mul(pool.allocPoint).div(totalAllocPoint);
uint256
finsReward
= multiplier.mul(
finsPerSecond
).mul(pool.allocPoint).div(totalAllocPoint);
cake
.mint(devaddr,
cakeReward
.div(10));
fins
.mint(devaddr,
finsReward
.div(10));
cake
.mint(address(
syrup
),
cakeReward
);
fins
.mint(address(
caviar
),
finsReward
);
pool.acc
Cake
PerShare = pool.acc
Cake
PerShare.add(
cakeReward
.mul(1e12).div(lpSupply));
pool.acc
Fins
PerShare = pool.acc
Fins
PerShare.add(
finsReward
.mul(1e12).div(lpSupply));
pool.lastReward
Block
= block.
number
;
pool.lastReward
Time
= block.
timestamp
;
}
}
コピー
コピー済み
コピー
コピー済み
// Deposit LP tokens to MasterChef for
CAKE
allocation.
// Deposit LP tokens to MasterChef for
FINS
allocation.
function deposit(uint256 _pid, uint256 _amount) public {
function deposit(uint256 _pid, uint256 _amount) public {
コピー
コピー済み
コピー
コピー済み
require (_pid != 0, 'deposit
CAKE
by staking');
require (_pid != 0, 'deposit
FINS
by staking');
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
updatePool(_pid);
if (user.amount > 0) {
if (user.amount > 0) {
コピー
コピー済み
コピー
コピー済み
uint256 pending = user.amount.mul(pool.acc
Cake
PerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.acc
Fins
PerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
コピー
コピー済み
コピー
コピー済み
safe
Cake
Transfer(msg.sender, pending);
safe
Fins
Transfer(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.acc
Cake
PerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.acc
Fins
PerShare).div(1e12);
emit Deposit(msg.sender, _pid, _amount);
emit Deposit(msg.sender, _pid, _amount);
}
}
// Withdraw LP tokens from MasterChef.
// Withdraw LP tokens from MasterChef.
function withdraw(uint256 _pid, uint256 _amount) public {
function withdraw(uint256 _pid, uint256 _amount) public {
コピー
コピー済み
コピー
コピー済み
require (_pid != 0, 'withdraw
CAKE
by unstaking');
require (_pid != 0, 'withdraw
FINS
by unstaking');
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.amount >= _amount, "withdraw: not good");
require(user.amount >= _amount, "withdraw: not good");
updatePool(_pid);
updatePool(_pid);
コピー
コピー済み
コピー
コピー済み
uint256 pending = user.amount.mul(pool.acc
Cake
PerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.acc
Fins
PerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
コピー
コピー済み
コピー
コピー済み
safe
Cake
Transfer(msg.sender, pending);
safe
Fins
Transfer(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.acc
Cake
PerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.acc
Fins
PerShare).div(1e12);
emit Withdraw(msg.sender, _pid, _amount);
emit Withdraw(msg.sender, _pid, _amount);
}
}
コピー
コピー済み
コピー
コピー済み
// Stake
CAKE
tokens to MasterChef
// Stake
FINS
tokens to MasterChef
function enterStaking(uint256 _amount) public {
function enterStaking(uint256 _amount) public {
PoolInfo storage pool = poolInfo[0];
PoolInfo storage pool = poolInfo[0];
UserInfo storage user = userInfo[0][msg.sender];
UserInfo storage user = userInfo[0][msg.sender];
updatePool(0);
updatePool(0);
if (user.amount > 0) {
if (user.amount > 0) {
コピー
コピー済み
コピー
コピー済み
uint256 pending = user.amount.mul(pool.acc
Cake
PerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.acc
Fins
PerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
コピー
コピー済み
コピー
コピー済み
safe
Cake
Transfer(msg.sender, pending);
safe
Fins
Transfer(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.acc
Cake
PerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.acc
Fins
PerShare).div(1e12);
コピー
コピー済み
コピー
コピー済み
syrup
.mint(msg.sender, _amount);
caviar
.mint(msg.sender, _amount);
emit Deposit(msg.sender, 0, _amount);
emit Deposit(msg.sender, 0, _amount);
}
}
コピー
コピー済み
コピー
コピー済み
// Withdraw
CAKE
tokens from STAKING.
// Withdraw
FINS
tokens from STAKING.
function leaveStaking(uint256 _amount) public {
function leaveStaking(uint256 _amount) public {
PoolInfo storage pool = poolInfo[0];
PoolInfo storage pool = poolInfo[0];
UserInfo storage user = userInfo[0][msg.sender];
UserInfo storage user = userInfo[0][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.acc
Cake
PerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.acc
Fins
PerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
コピー
コピー済み
コピー
コピー済み
safe
Cake
Transfer(msg.sender, pending);
safe
Fins
Transfer(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.acc
Cake
PerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.acc
Fins
PerShare).div(1e12);
コピー
コピー済み
コピー
コピー済み
syrup
.burn(msg.sender, _amount);
caviar
.burn(msg.sender, _amount);
emit Withdraw(msg.sender, 0, _amount);
emit Withdraw(msg.sender, 0, _amount);
}
}
// Withdraw without caring about rewards. EMERGENCY ONLY.
// Withdraw without caring about rewards. EMERGENCY ONLY.
function emergencyWithdraw(uint256 _pid) public {
function emergencyWithdraw(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];
pool.lpToken.safeTransfer(address(msg.sender), user.amount);
pool.lpToken.safeTransfer(address(msg.sender), user.amount);
emit EmergencyWithdraw(msg.sender, _pid, user.amount);
emit EmergencyWithdraw(msg.sender, _pid, user.amount);
user.amount = 0;
user.amount = 0;
user.rewardDebt = 0;
user.rewardDebt = 0;
}
}
コピー
コピー済み
コピー
コピー済み
// Safe
cake
transfer function, just in case if rounding error causes pool to not have enough
CAKEs
.
// Safe
fins
transfer function, just in case if rounding error causes pool to not have enough
fins
.
function safe
Cake
Transfer(address _to, uint256 _amount) internal {
function safe
Fins
Transfer(address _to, uint256 _amount) internal {
syrup
.safe
Cake
Transfer(_to, _amount);
caviar
.safe
Fins
Transfer(_to, _amount);
}
}
// Update dev address by the previous dev.
// Update dev address by the previous dev.
コピー
コピー済み
コピー
コピー済み
function
dev
(address _devaddr) public {
function
setDevAddress
(address _devaddr) public {
require(msg.sender == devaddr, "dev: wut?");
require(msg.sender == devaddr, "dev: wut?");
devaddr = _devaddr;
devaddr = _devaddr;
}
}
コピー
コピー済み
コピー
コピー済み
function setFinsPerSecond(uint256 _finsPerSecond) public onlyOwner {
require(_finsPerSecond <= maxFinsPerSecond, "finsPerSecond: ol?");
massUpdatePools();
finsPerSecond = _finsPerSecond;
}
}
}
保存された差分
原文
ファイルを開く
pragma solidity 0.6.12; 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'; import "./CakeToken.sol"; import "./SyrupBar.sol"; // import "@nomiclabs/buidler/console.sol"; interface IMigratorChef { // Perform LP token migration from legacy PancakeSwap to CakeSwap. // Take the current LP token address and return the new LP token address. // Migrator should have full access to the caller's LP token. // Return the new LP token address. // // XXX Migrator must have allowance access to PancakeSwap LP tokens. // CakeSwap must mint EXACTLY the same amount of CakeSwap LP tokens or // else something bad will happen. Traditional PancakeSwap does not // do that so be careful! function migrate(IBEP20 token) external returns (IBEP20); } // MasterChef is the master of Cake. He can make Cake and he is a fair guy. // // Note that it's ownable and the owner wields tremendous power. The ownership // will be transferred to a governance smart contract once CAKE is sufficiently // distributed and the community can show to govern itself. // // Have fun reading it. Hopefully it's bug-free. God bless. contract MasterChef 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. // // We do some fancy math here. Basically, any point in time, the amount of CAKEs // entitled to a user but is pending to be distributed is: // // pending reward = (user.amount * pool.accCakePerShare) - user.rewardDebt // // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: // 1. The pool's `accCakePerShare` (and `lastRewardBlock`) gets updated. // 2. User receives the pending reward sent to his/her address. // 3. User's `amount` gets updated. // 4. User's `rewardDebt` gets updated. } // Info of each pool. struct PoolInfo { IBEP20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. CAKEs to distribute per block. uint256 lastRewardBlock; // Last block number that CAKEs distribution occurs. uint256 accCakePerShare; // Accumulated CAKEs per share, times 1e12. See below. } // The CAKE TOKEN! CakeToken public cake; // The SYRUP TOKEN! SyrupBar public syrup; // Dev address. address public devaddr; // CAKE tokens created per block. uint256 public cakePerBlock; // Bonus muliplier for early cake makers. uint256 public BONUS_MULTIPLIER = 1; // The migrator contract. It has a lot of power. Can only be set through governance (owner). IMigratorChef public migrator; // Info of each pool. PoolInfo[] public poolInfo; // Info of each user that stakes LP tokens. mapping (uint256 => mapping (address => UserInfo)) public userInfo; // Total allocation points. Must be the sum of all allocation points in all pools. uint256 public totalAllocPoint = 0; // The block number when CAKE mining starts. uint256 public startBlock; event Deposit(address indexed user, uint256 indexed pid, uint256 amount); event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); constructor( CakeToken _cake, SyrupBar _syrup, address _devaddr, uint256 _cakePerBlock, uint256 _startBlock ) public { cake = _cake; syrup = _syrup; devaddr = _devaddr; cakePerBlock = _cakePerBlock; startBlock = _startBlock; // staking pool poolInfo.push(PoolInfo({ lpToken: _cake, allocPoint: 1000, lastRewardBlock: startBlock, accCakePerShare: 0 })); totalAllocPoint = 1000; } function updateMultiplier(uint256 multiplierNumber) public onlyOwner { BONUS_MULTIPLIER = multiplierNumber; } function poolLength() external view returns (uint256) { return poolInfo.length; } // Add a new lp to the pool. Can only be called by the owner. // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. function add(uint256 _allocPoint, IBEP20 _lpToken, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock; totalAllocPoint = totalAllocPoint.add(_allocPoint); poolInfo.push(PoolInfo({ lpToken: _lpToken, allocPoint: _allocPoint, lastRewardBlock: lastRewardBlock, accCakePerShare: 0 })); updateStakingPool(); } // Update the given pool's CAKE allocation point. Can only be called by the owner. function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } uint256 prevAllocPoint = poolInfo[_pid].allocPoint; poolInfo[_pid].allocPoint = _allocPoint; if (prevAllocPoint != _allocPoint) { totalAllocPoint = totalAllocPoint.sub(prevAllocPoint).add(_allocPoint); updateStakingPool(); } } function updateStakingPool() internal { uint256 length = poolInfo.length; uint256 points = 0; for (uint256 pid = 1; pid < length; ++pid) { points = points.add(poolInfo[pid].allocPoint); } if (points != 0) { points = points.div(3); totalAllocPoint = totalAllocPoint.sub(poolInfo[0].allocPoint).add(points); poolInfo[0].allocPoint = points; } } // Set the migrator contract. Can only be called by the owner. function setMigrator(IMigratorChef _migrator) public onlyOwner { migrator = _migrator; } // Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good. function migrate(uint256 _pid) public { require(address(migrator) != address(0), "migrate: no migrator"); PoolInfo storage pool = poolInfo[_pid]; IBEP20 lpToken = pool.lpToken; uint256 bal = lpToken.balanceOf(address(this)); lpToken.safeApprove(address(migrator), bal); IBEP20 newLpToken = migrator.migrate(lpToken); require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); pool.lpToken = newLpToken; } // Return reward multiplier over the given _from to _to block. function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { return _to.sub(_from).mul(BONUS_MULTIPLIER); } // View function to see pending CAKEs on frontend. function pendingCake(uint256 _pid, address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 accCakePerShare = pool.accCakePerShare; uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (block.number > pool.lastRewardBlock && lpSupply != 0) { uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 cakeReward = multiplier.mul(cakePerBlock).mul(pool.allocPoint).div(totalAllocPoint); accCakePerShare = accCakePerShare.add(cakeReward.mul(1e12).div(lpSupply)); } return user.amount.mul(accCakePerShare).div(1e12).sub(user.rewardDebt); } // 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); } } // 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 cakeReward = multiplier.mul(cakePerBlock).mul(pool.allocPoint).div(totalAllocPoint); cake.mint(devaddr, cakeReward.div(10)); cake.mint(address(syrup), cakeReward); pool.accCakePerShare = pool.accCakePerShare.add(cakeReward.mul(1e12).div(lpSupply)); pool.lastRewardBlock = block.number; } // Deposit LP tokens to MasterChef for CAKE allocation. function deposit(uint256 _pid, uint256 _amount) public { require (_pid != 0, 'deposit CAKE by staking'); PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; updatePool(_pid); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accCakePerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeCakeTransfer(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.accCakePerShare).div(1e12); emit Deposit(msg.sender, _pid, _amount); } // Withdraw LP tokens from MasterChef. function withdraw(uint256 _pid, uint256 _amount) public { require (_pid != 0, 'withdraw CAKE by unstaking'); 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.mul(pool.accCakePerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeCakeTransfer(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.accCakePerShare).div(1e12); emit Withdraw(msg.sender, _pid, _amount); } // Stake CAKE tokens to MasterChef function enterStaking(uint256 _amount) public { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[0][msg.sender]; updatePool(0); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accCakePerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeCakeTransfer(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.accCakePerShare).div(1e12); syrup.mint(msg.sender, _amount); emit Deposit(msg.sender, 0, _amount); } // Withdraw CAKE tokens from STAKING. function leaveStaking(uint256 _amount) public { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[0][msg.sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(0); uint256 pending = user.amount.mul(pool.accCakePerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeCakeTransfer(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.accCakePerShare).div(1e12); syrup.burn(msg.sender, _amount); emit Withdraw(msg.sender, 0, _amount); } // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; pool.lpToken.safeTransfer(address(msg.sender), user.amount); emit EmergencyWithdraw(msg.sender, _pid, user.amount); user.amount = 0; user.rewardDebt = 0; } // Safe cake transfer function, just in case if rounding error causes pool to not have enough CAKEs. function safeCakeTransfer(address _to, uint256 _amount) internal { syrup.safeCakeTransfer(_to, _amount); } // Update dev address by the previous dev. function dev(address _devaddr) public { require(msg.sender == devaddr, "dev: wut?"); devaddr = _devaddr; } }
変更されたテキスト
ファイルを開く
// SPDX-License-Identifier: MIT pragma solidity 0.6.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/utils/EnumerableSet.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./FinToken.sol"; import "./CaviarBar.sol"; interface IMigratorChef { // Perform LP token migration from legacy FinSwap to new FinSwap. // Take the current LP token address and return the new LP token address. // Migrator should have full access to the caller's LP token. // Return the new LP token address. // // XXX Migrator must have allowance access to FinSwap LP tokens. // FinSwap must mint EXACTLY the same amount of FinSwap LP tokens or // else something bad will happen. Traditional FinSwap does not // do that so be careful! function migrate(IERC20 token) external returns (IERC20); } // MasterChef is the master of Fins. He can make Fins and he is a fair guy. // // Note that it's ownable and the owner wields tremendous power. The ownership // will be transferred to a governance smart contract once FINS is sufficiently // distributed and the community can show to govern itself. // // Have fun reading it. Hopefully it's bug-free. God bless. contract MasterChef is Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. // // We do some fancy math here. Basically, any point in time, the amount of FINSs // entitled to a user but is pending to be distributed is: // // pending reward = (user.amount * pool.accFinsPerShare) - user.rewardDebt // // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: // 1. The pool's `accFinsPerShare` (and `lastRewardTime`) gets updated. // 2. User receives the pending reward sent to his/her address. // 3. User's `amount` gets updated. // 4. User's `rewardDebt` gets updated. } // Info of each pool. struct PoolInfo { IERC20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. FINS to distribute per block. uint256 lastRewardTime; // Last block number that FINS distribution occurs. uint256 accFinsPerShare; // Accumulated FINS per share, times 1e12. See below. } // The FINS TOKEN! FinToken public fins; // The caviar TOKEN! CaviarBar public caviar; // Dev address. address public devaddr; // FINS tokens created per second. uint256 public finsPerSecond; // Max finsPerSecond keep never ol uint256 public constant maxFinsPerSecond = 1e18; // The migrator contract. It has a lot of power. Can only be set through governance (owner). IMigratorChef public migrator; // Info of each pool. PoolInfo[] public poolInfo; // add the same LP token only once mapping(address => bool) lpExists; // Info of each user that stakes LP tokens. mapping (uint256 => mapping (address => UserInfo)) public userInfo; // Total allocation points. Must be the sum of all allocation points in all pools. uint256 public totalAllocPoint = 0; // The block number when FINS mining starts. uint256 public startTime; event Deposit(address indexed user, uint256 indexed pid, uint256 amount); event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); constructor( FinToken _fins, CaviarBar _caviar, address _devaddr, uint256 _finsPerSecond, uint256 _startTime ) public { fins = _fins; caviar = _caviar; devaddr = _devaddr; finsPerSecond = _finsPerSecond; startTime = _startTime; // staking pool poolInfo.push(PoolInfo({ lpToken: _fins, allocPoint: 1000, lastRewardTime: startTime, accFinsPerShare: 0 })); totalAllocPoint = 1000; } function poolLength() external view returns (uint256) { return poolInfo.length; } // Add a new lp to the pool. Can only be called by the owner. // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner { require(!lpExists[address(_lpToken)], "!lpToken exists"); if (_withUpdate) { massUpdatePools(); } uint256 lastRewardTime = block.timestamp > startTime ? block.timestamp : startTime; totalAllocPoint = totalAllocPoint.add(_allocPoint); poolInfo.push(PoolInfo({ lpToken: _lpToken, allocPoint: _allocPoint, lastRewardTime: lastRewardTime, accFinsPerShare: 0 })); updateStakingPool(); lpExists[address(_lpToken)] = true; } // Update the given pool's FINS allocation point. Can only be called by the owner. function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } uint256 prevAllocPoint = poolInfo[_pid].allocPoint; poolInfo[_pid].allocPoint = _allocPoint; if (prevAllocPoint != _allocPoint) { totalAllocPoint = totalAllocPoint.sub(prevAllocPoint).add(_allocPoint); updateStakingPool(); } } function updateStakingPool() internal { uint256 length = poolInfo.length; uint256 points = 0; for (uint256 pid = 1; pid < length; ++pid) { points = points.add(poolInfo[pid].allocPoint); } if (points != 0) { points = points.div(3); totalAllocPoint = totalAllocPoint.sub(poolInfo[0].allocPoint).add(points); poolInfo[0].allocPoint = points; } } // Set the migrator contract. Can only be called by the owner. function setMigrator(IMigratorChef _migrator) public onlyOwner { migrator = _migrator; } // Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good. function migrate(uint256 _pid) public { require(address(migrator) != address(0), "migrate: no migrator"); PoolInfo storage pool = poolInfo[_pid]; IERC20 lpToken = pool.lpToken; uint256 bal = lpToken.balanceOf(address(this)); lpToken.safeApprove(address(migrator), bal); IERC20 newLpToken = migrator.migrate(lpToken); require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); pool.lpToken = newLpToken; } // Return reward multiplier over the given _from to _to block. function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { _from = _from > startTime ? _from : startTime; if (_to < startTime) { return 0; } return _to.sub(_from); } // View function to see pending FINS on frontend. function pendingFins(uint256 _pid, address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 accFinsPerShare = pool.accFinsPerShare; uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (block.timestamp > pool.lastRewardTime && lpSupply != 0) { uint256 multiplier = getMultiplier(pool.lastRewardTime, block.timestamp); uint256 finsReward = multiplier.mul(finsPerSecond).mul(pool.allocPoint).div(totalAllocPoint); accFinsPerShare = accFinsPerShare.add(finsReward.mul(1e12).div(lpSupply)); } return user.amount.mul(accFinsPerShare).div(1e12).sub(user.rewardDebt); } // 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); } } // Update reward variables of the given pool to be up-to-date. function updatePool(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; if (block.timestamp <= pool.lastRewardTime) { return; } uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (lpSupply == 0) { pool.lastRewardTime = block.timestamp; return; } uint256 multiplier = getMultiplier(pool.lastRewardTime, block.timestamp); uint256 finsReward = multiplier.mul(finsPerSecond).mul(pool.allocPoint).div(totalAllocPoint); fins.mint(devaddr, finsReward.div(10)); fins.mint(address(caviar), finsReward); pool.accFinsPerShare = pool.accFinsPerShare.add(finsReward.mul(1e12).div(lpSupply)); pool.lastRewardTime = block.timestamp; } // Deposit LP tokens to MasterChef for FINS allocation. function deposit(uint256 _pid, uint256 _amount) public { require (_pid != 0, 'deposit FINS by staking'); PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; updatePool(_pid); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accFinsPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeFinsTransfer(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.accFinsPerShare).div(1e12); emit Deposit(msg.sender, _pid, _amount); } // Withdraw LP tokens from MasterChef. function withdraw(uint256 _pid, uint256 _amount) public { require (_pid != 0, 'withdraw FINS by unstaking'); 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.mul(pool.accFinsPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeFinsTransfer(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.accFinsPerShare).div(1e12); emit Withdraw(msg.sender, _pid, _amount); } // Stake FINS tokens to MasterChef function enterStaking(uint256 _amount) public { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[0][msg.sender]; updatePool(0); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accFinsPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeFinsTransfer(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.accFinsPerShare).div(1e12); caviar.mint(msg.sender, _amount); emit Deposit(msg.sender, 0, _amount); } // Withdraw FINS tokens from STAKING. function leaveStaking(uint256 _amount) public { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[0][msg.sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(0); uint256 pending = user.amount.mul(pool.accFinsPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeFinsTransfer(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.accFinsPerShare).div(1e12); caviar.burn(msg.sender, _amount); emit Withdraw(msg.sender, 0, _amount); } // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; pool.lpToken.safeTransfer(address(msg.sender), user.amount); emit EmergencyWithdraw(msg.sender, _pid, user.amount); user.amount = 0; user.rewardDebt = 0; } // Safe fins transfer function, just in case if rounding error causes pool to not have enough fins. function safeFinsTransfer(address _to, uint256 _amount) internal { caviar.safeFinsTransfer(_to, _amount); } // Update dev address by the previous dev. function setDevAddress(address _devaddr) public { require(msg.sender == devaddr, "dev: wut?"); devaddr = _devaddr; } function setFinsPerSecond(uint256 _finsPerSecond) public onlyOwner { require(_finsPerSecond <= maxFinsPerSecond, "finsPerSecond: ol?"); massUpdatePools(); finsPerSecond = _finsPerSecond; } }
違いを見つける