Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
ライブエディター
空白の変更を非表示
未変更行を折りたたむ
折り返しなし
レイアウト
分割
統合
比較精度
スマート
単語
文字
テキストスタイル
外観を変更
シンタックスハイライト
構文を選択
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
synthetix_maple_liquidity_mining_diff
作成日
5 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
106 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
177 行
すべてコピー
146 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
215 行
すべてコピー
コピー
コピー済み
コピー
コピー済み
pragma solidity ^0.5.16;
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.6.11;
import "openzeppelin-solidity-2.3.0/contracts/math/Math.sol";
import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol";
import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/ERC20Detailed.sol";
import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/SafeERC20.sol";
import "openzeppelin-solidity-2.3.0/contracts/utils/ReentrancyGuard.sol";
コピー
コピー済み
コピー
コピー済み
// Inheritance
import "lib/openzeppelin-contracts/contracts/access/Ownable.sol";
import "
./interfaces/IStakingRewards
.sol";
import "
lib/openzeppelin-contracts/contracts/math/Math
.sol";
import "
./RewardsDistributionRecipient
.sol";
import "
lib/openzeppelin-contracts/contracts/math/SafeMath
.sol";
import "
./Pausable
.sol";
import "
lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20
.sol";
コピー
コピー済み
コピー
コピー済み
import "./interfaces/IERC2258.sol";
// https://docs.synthetix.io/contracts/source/contracts/stakingrewards
// https://docs.synthetix.io/contracts/source/contracts/stakingrewards
コピー
コピー済み
コピー
コピー済み
contract
StakingRewards
is
IStakingRewards, RewardsDistributionRecipient, ReentrancyGuard, Pausable
{
/// @title MplRewards Synthetix farming
contract
fork for liquidity mining.
using SafeMath
for uint256;
contract MplRewards
is
Ownable
{
using SafeMath
for uint256;
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;
コピー
コピー済み
コピー
コピー済み
/* ========== STATE VARIABLES ========== */
IERC20 public immutable rewardsToken;
IERC2258 public immutable stakingToken;
コピー
コピー済み
コピー
コピー済み
IERC20 public rewardsToken;
uint256 public periodFinish
;
IERC20 public stakingToken;
uint256 public rewardRate
;
uint256 public periodFinish
= 0
;
uint256 public rewardsDuration
;
uint256 public rewardRate
= 0
;
uint256 public rewardsDuration
= 7 days
;
uint256 public lastUpdateTime;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
uint256 public rewardPerTokenStored;
コピー
コピー済み
コピー
コピー済み
uint256 public lastPauseTime;
bool public paused;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public rewards;
uint256 private _totalSupply;
uint256 private _totalSupply;
コピー
コピー済み
コピー
コピー済み
mapping(address => uint256) private _balances;
mapping(address => uint256) private _balances;
コピー
コピー済み
コピー
コピー済み
/* ========== CONSTRUCTOR ========== */
event RewardAdded(uint256 reward);
event Staked(address indexed account, uint256 amount);
event Withdrawn(address indexed account, uint256 amount);
event RewardPaid(address indexed account, uint256 reward);
event RewardsDurationUpdated(uint256 newDuration);
event Recovered(address token, uint256 amount);
event PauseChanged(bool isPaused);
コピー
コピー済み
コピー
コピー済み
constructor(
constructor(
address _rewardsToken,
address _stakingToken
, address _owner
) public
{
address _owner,
rewardsToken
= IERC20(_rewardsToken);
address _rewardsDistribution,
stakingToken
= IERC2
258
(_stakingToken);
address _rewardsToken,
rewardsD
ura
tion =
7 days;
address _stakingToken
transferOwnership(_owner)
;
) public
Owned(_owner)
{
rewardsToken
= IERC20(_rewardsToken);
stakingToken
= IERC2
0
(_stakingToken);
rewardsD
istribu
tion =
_rewardsDistribution
;
}
}
コピー
コピー済み
コピー
コピー済み
/* ========== VIEWS ========== */
function _updateReward(address account) internal {
uint256 _rewardPerTokenStored = rewardPerToken();
rewardPerTokenStored = _rewardPerTokenStored;
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = _rewardPerTokenStored;
}
}
function _notPaused() internal view {
require(!paused, "R:PAUSED");
}
function totalSupply() external view returns (uint256) {
function totalSupply() external view returns (uint256) {
return _totalSupply;
return _totalSupply;
}
}
function balanceOf(address account) external view returns (uint256) {
function balanceOf(address account) external view returns (uint256) {
return _balances[account];
return _balances[account];
}
}
function lastTimeRewardApplicable() public view returns (uint256) {
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
return Math.min(block.timestamp, periodFinish);
}
}
function rewardPerToken() public view returns (uint256) {
function rewardPerToken() public view returns (uint256) {
コピー
コピー済み
コピー
コピー済み
if (
_totalSupply == 0
) {
return
_totalSupply == 0
return
rewardPerTokenStored
;
?
rewardPerTokenStored
}
:
rewardPerTokenStored.add(
return
lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply)
rewardPerTokenStored.add(
);
lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply)
);
}
}
function earned(address account) public view returns (uint256) {
function earned(address account) public view returns (uint256) {
return _balances[account].mul(rewardPerToken().sub(userRewardPerTokenPaid[account])).div(1e18).add(rewards[account]);
return _balances[account].mul(rewardPerToken().sub(userRewardPerTokenPaid[account])).div(1e18).add(rewards[account]);
}
}
function getRewardForDuration() external view returns (uint256) {
function getRewardForDuration() external view returns (uint256) {
return rewardRate.mul(rewardsDuration);
return rewardRate.mul(rewardsDuration);
}
}
コピー
コピー済み
コピー
コピー済み
/*
========== MUTATIVE FUNCTIONS ==========
*/
/*
*
@dev It emits a `Staked` event.
function stake(uint256 amount) external
nonReentrant
notPaused
updateReward(msg.sender)
{
*/
require(amount > 0, "
Cannot stake 0");
function stake(uint256 amount) external
{
_totalSupply
= _totalSupply.add(amount);
_
notPaused
();
_balances[msg.sender] =
_b
alance
s[msg.sender].add(amount);
_
updateReward(msg.sender)
;
stakingToken.safeTransferFrom(msg.sender, address(this), amount)
;
uint256 newBalance = _balances[msg.sender].add(amount);
require(amount > 0, "
R:ZERO_STAKE");
require(stakingToken.custodyAllowance(msg.sender, address(this)) >= newBalance, "R:INSUF_CUST_ALLOWANCE");
_totalSupply
= _totalSupply.add(amount);
_balances[msg.sender] =
newB
alance
;
emit Staked(msg.sender, amount);
emit Staked(msg.sender, amount);
}
}
コピー
コピー済み
コピー
コピー済み
function withdraw(uint256 amount) public
nonReentrant
updateReward(msg.sender)
{
/**
require(amount > 0, "
Cannot withdraw 0
");
@dev It emits a `Withdrawn` event.
*/
function withdraw(uint256 amount) public
{
_notPaused();
_
updateReward(msg.sender)
;
require(amount > 0, "
R:ZERO_WITHDRAW
");
_totalSupply = _totalSupply.sub(amount);
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
コピー
コピー済み
コピー
コピー済み
stakingToken.
safeTransfer
(msg.sender,
amount);
stakingToken.
transferByCustodian
(msg.sender,
msg.sender,
amount);
emit Withdrawn(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
}
コピー
コピー済み
コピー
コピー済み
function getReward() public
nonReentrant
updateReward(msg.sender)
{
/**
@dev It emits a `RewardPaid` event if any rewards are received.
*/
function getReward() public
{
_notPaused();
_
updateReward(msg.sender)
;
uint256 reward = rewards[msg.sender];
uint256 reward = rewards[msg.sender];
コピー
コピー済み
コピー
コピー済み
if (reward
> 0) {
rewards[msg.sender] =
0;
if (reward
== uint256(0)) return;
rewardsToken.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
rewards[msg.sender] =
uint256(0);
}
rewardsToken.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function exit() external {
function exit() external {
withdraw(_balances[msg.sender]);
withdraw(_balances[msg.sender]);
getReward();
getReward();
}
}
コピー
コピー済み
コピー
コピー済み
/* ========== RESTRICTED FUNCTIONS ========== */
/**
@dev Only the contract Owner may call this.
@dev It emits a `RewardAdded` event.
*/
function notifyRewardAmount(uint256 reward) external onlyOwner {
_updateReward(address(0));
コピー
コピー済み
コピー
コピー済み
function notifyRewardAmount(
uint256
reward) external onlyRewardsDistribution updateReward(address(0)) {
uint256
_rewardRate =
block.timestamp >= periodFinish
if (
block.timestamp >= periodFinish
) {
?
reward.div(rewardsDuration)
rewardRate =
reward.div(rewardsDuration)
;
: reward.add(
} else {
periodFinish.sub(block.timestamp)
.mul(rewardRate)
uint256 remaining =
periodFinish.sub(block.timestamp)
;
).div(rewardsDuration);
uint256 leftover = remaining
.mul(rewardRate)
;
rewardRate = reward.add(leftover
).div(rewardsDuration);
rewardRate = _rewardRate;
}
// Ensure the provided reward amount is not more than the balance in the contract.
// Ensure the provided reward amount is not more than the balance in the contract.
// This keeps the reward rate in the right range, preventing overflows due to
// This keeps the reward rate in the right range, preventing overflows due to
// very high values of rewardRate in the earned and rewardsPerToken functions;
// very high values of rewardRate in the earned and rewardsPerToken functions;
// Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
// Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
コピー
コピー済み
コピー
コピー済み
uint
balance = rewardsToken.balanceOf(address(this));
uint
256
balance = rewardsToken.balanceOf(address(this));
require(
rewardRate <= balance.div(rewardsDuration), "
Provided reward too high
");
require(
_
rewardRate <= balance.div(rewardsDuration), "
R:REWARD_TOO_HIGH
");
lastUpdateTime = block.timestamp;
lastUpdateTime = block.timestamp;
コピー
コピー済み
コピー
コピー済み
periodFinish
= block.timestamp.add(rewardsDuration);
periodFinish
= block.timestamp.add(rewardsDuration);
emit RewardAdded(reward);
emit RewardAdded(reward);
}
}
コピー
コピー済み
コピー
コピー済み
/
/
End rewards emission earlier
/
**
function updatePeriodFinish(uint
timestamp) external onlyOwner
updateReward(address(0))
{
@dev
End rewards emission earlier
. Only the contract Owner may call this.
*/
function updatePeriodFinish(uint
256
timestamp) external onlyOwner
{
_
updateReward(address(0))
;
periodFinish = timestamp;
periodFinish = timestamp;
}
}
コピー
コピー済み
コピー
コピー済み
/
/
Added to support recovering
LP Rewards from other systems such as BAL to be distributed to holders
/
**
@dev
Added to support recovering
tokens unintentionally sent to this contract.
Only the contract Owner may call this.
@dev It emits a `Recovered` event.
*/
function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {
function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {
コピー
コピー済み
コピー
コピー済み
require(tokenAddress != address(stakingToken), "Cannot withdraw the staking token");
IERC20(tokenAddress).safeTransfer(owner
()
, tokenAmount);
IERC20(tokenAddress).safeTransfer(owner
, tokenAmount);
emit Recovered(tokenAddress, tokenAmount);
emit Recovered(tokenAddress, tokenAmount);
}
}
コピー
コピー済み
コピー
コピー済み
/**
@dev Only the contract Owner may call this.
@dev It emits a `RewardsDurationUpdated` event.
*/
function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner {
function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner {
コピー
コピー済み
コピー
コピー済み
require(
require(
block.timestamp > periodFinish,
"R:PERIOD_NOT_FINISHED");
block.timestamp > periodFinish,
"Previous rewards period must be complete before changing the duration for the new period"
);
rewardsDuration = _rewardsDuration;
rewardsDuration = _rewardsDuration;
emit RewardsDurationUpdated(rewardsDuration);
emit RewardsDurationUpdated(rewardsDuration);
}
}
コピー
コピー済み
コピー
コピー済み
/* ========== MODIFIERS ========== */
/**
@dev Change the paused state of the contract. Only the contract Owner may call this.
@dev It emits a `PauseChanged` event.
*/
function setPaused(bool _paused) external onlyOwner {
// Ensure we're actually changing the state before we do anything
require(_paused != paused, "R:ALREADY_SET");
コピー
コピー済み
コピー
コピー済み
modifier updateReward(address account) {
// Set our paused state.
rewardPerTokenStored = rewardPerToken();
paused = _paused;
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
// If applicable, set the last pause time.
rewards[account] = earned(account);
if (_paused) lastPauseTime = block.timestamp;
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
// Let everyone know that our pause state has changed.
_;
emit PauseChanged(paused);
}
}
コピー
コピー済み
コピー
コピー済み
/* ========== EVENTS ========== */
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
event RewardsDurationUpdated(uint256 newDuration);
event Recovered(address token, uint256 amount);
}
}
コピー
コピー済み
コピー
コピー済み
{"mode":"full","isActive":false}
保存された差分
原文
ファイルを開く
pragma solidity ^0.5.16; import "openzeppelin-solidity-2.3.0/contracts/math/Math.sol"; import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol"; import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/ERC20Detailed.sol"; import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/SafeERC20.sol"; import "openzeppelin-solidity-2.3.0/contracts/utils/ReentrancyGuard.sol"; // Inheritance import "./interfaces/IStakingRewards.sol"; import "./RewardsDistributionRecipient.sol"; import "./Pausable.sol"; // https://docs.synthetix.io/contracts/source/contracts/stakingrewards contract StakingRewards is IStakingRewards, RewardsDistributionRecipient, ReentrancyGuard, Pausable { using SafeMath for uint256; using SafeERC20 for IERC20; /* ========== STATE VARIABLES ========== */ IERC20 public rewardsToken; IERC20 public stakingToken; uint256 public periodFinish = 0; uint256 public rewardRate = 0; uint256 public rewardsDuration = 7 days; uint256 public lastUpdateTime; uint256 public rewardPerTokenStored; mapping(address => uint256) public userRewardPerTokenPaid; mapping(address => uint256) public rewards; uint256 private _totalSupply; mapping(address => uint256) private _balances; /* ========== CONSTRUCTOR ========== */ constructor( address _owner, address _rewardsDistribution, address _rewardsToken, address _stakingToken ) public Owned(_owner) { rewardsToken = IERC20(_rewardsToken); stakingToken = IERC20(_stakingToken); rewardsDistribution = _rewardsDistribution; } /* ========== VIEWS ========== */ function totalSupply() external view returns (uint256) { return _totalSupply; } function balanceOf(address account) external view returns (uint256) { return _balances[account]; } function lastTimeRewardApplicable() public view returns (uint256) { return Math.min(block.timestamp, periodFinish); } function rewardPerToken() public view returns (uint256) { if (_totalSupply == 0) { return rewardPerTokenStored; } return rewardPerTokenStored.add( lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply) ); } function earned(address account) public view returns (uint256) { return _balances[account].mul(rewardPerToken().sub(userRewardPerTokenPaid[account])).div(1e18).add(rewards[account]); } function getRewardForDuration() external view returns (uint256) { return rewardRate.mul(rewardsDuration); } /* ========== MUTATIVE FUNCTIONS ========== */ function stake(uint256 amount) external nonReentrant notPaused updateReward(msg.sender) { require(amount > 0, "Cannot stake 0"); _totalSupply = _totalSupply.add(amount); _balances[msg.sender] = _balances[msg.sender].add(amount); stakingToken.safeTransferFrom(msg.sender, address(this), amount); emit Staked(msg.sender, amount); } function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) { require(amount > 0, "Cannot withdraw 0"); _totalSupply = _totalSupply.sub(amount); _balances[msg.sender] = _balances[msg.sender].sub(amount); stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount); } function getReward() public nonReentrant updateReward(msg.sender) { uint256 reward = rewards[msg.sender]; if (reward > 0) { rewards[msg.sender] = 0; rewardsToken.safeTransfer(msg.sender, reward); emit RewardPaid(msg.sender, reward); } } function exit() external { withdraw(_balances[msg.sender]); getReward(); } /* ========== RESTRICTED FUNCTIONS ========== */ function notifyRewardAmount(uint256 reward) external onlyRewardsDistribution updateReward(address(0)) { if (block.timestamp >= periodFinish) { rewardRate = reward.div(rewardsDuration); } else { uint256 remaining = periodFinish.sub(block.timestamp); uint256 leftover = remaining.mul(rewardRate); rewardRate = reward.add(leftover).div(rewardsDuration); } // Ensure the provided reward amount is not more than the balance in the contract. // This keeps the reward rate in the right range, preventing overflows due to // very high values of rewardRate in the earned and rewardsPerToken functions; // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow. uint balance = rewardsToken.balanceOf(address(this)); require(rewardRate <= balance.div(rewardsDuration), "Provided reward too high"); lastUpdateTime = block.timestamp; periodFinish = block.timestamp.add(rewardsDuration); emit RewardAdded(reward); } // End rewards emission earlier function updatePeriodFinish(uint timestamp) external onlyOwner updateReward(address(0)) { periodFinish = timestamp; } // Added to support recovering LP Rewards from other systems such as BAL to be distributed to holders function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner { require(tokenAddress != address(stakingToken), "Cannot withdraw the staking token"); IERC20(tokenAddress).safeTransfer(owner, tokenAmount); emit Recovered(tokenAddress, tokenAmount); } function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner { require( block.timestamp > periodFinish, "Previous rewards period must be complete before changing the duration for the new period" ); rewardsDuration = _rewardsDuration; emit RewardsDurationUpdated(rewardsDuration); } /* ========== MODIFIERS ========== */ modifier updateReward(address account) { rewardPerTokenStored = rewardPerToken(); lastUpdateTime = lastTimeRewardApplicable(); if (account != address(0)) { rewards[account] = earned(account); userRewardPerTokenPaid[account] = rewardPerTokenStored; } _; } /* ========== EVENTS ========== */ event RewardAdded(uint256 reward); event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardPaid(address indexed user, uint256 reward); event RewardsDurationUpdated(uint256 newDuration); event Recovered(address token, uint256 amount); }
変更されたテキスト
ファイルを開く
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.6.11; import "lib/openzeppelin-contracts/contracts/access/Ownable.sol"; import "lib/openzeppelin-contracts/contracts/math/Math.sol"; import "lib/openzeppelin-contracts/contracts/math/SafeMath.sol"; import "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol"; import "./interfaces/IERC2258.sol"; // https://docs.synthetix.io/contracts/source/contracts/stakingrewards /// @title MplRewards Synthetix farming contract fork for liquidity mining. contract MplRewards is Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; IERC20 public immutable rewardsToken; IERC2258 public immutable stakingToken; uint256 public periodFinish; uint256 public rewardRate; uint256 public rewardsDuration; uint256 public lastUpdateTime; uint256 public rewardPerTokenStored; uint256 public lastPauseTime; bool public paused; mapping(address => uint256) public userRewardPerTokenPaid; mapping(address => uint256) public rewards; uint256 private _totalSupply; mapping(address => uint256) private _balances; event RewardAdded(uint256 reward); event Staked(address indexed account, uint256 amount); event Withdrawn(address indexed account, uint256 amount); event RewardPaid(address indexed account, uint256 reward); event RewardsDurationUpdated(uint256 newDuration); event Recovered(address token, uint256 amount); event PauseChanged(bool isPaused); constructor(address _rewardsToken, address _stakingToken, address _owner) public { rewardsToken = IERC20(_rewardsToken); stakingToken = IERC2258(_stakingToken); rewardsDuration = 7 days; transferOwnership(_owner); } function _updateReward(address account) internal { uint256 _rewardPerTokenStored = rewardPerToken(); rewardPerTokenStored = _rewardPerTokenStored; lastUpdateTime = lastTimeRewardApplicable(); if (account != address(0)) { rewards[account] = earned(account); userRewardPerTokenPaid[account] = _rewardPerTokenStored; } } function _notPaused() internal view { require(!paused, "R:PAUSED"); } function totalSupply() external view returns (uint256) { return _totalSupply; } function balanceOf(address account) external view returns (uint256) { return _balances[account]; } function lastTimeRewardApplicable() public view returns (uint256) { return Math.min(block.timestamp, periodFinish); } function rewardPerToken() public view returns (uint256) { return _totalSupply == 0 ? rewardPerTokenStored : rewardPerTokenStored.add( lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply) ); } function earned(address account) public view returns (uint256) { return _balances[account].mul(rewardPerToken().sub(userRewardPerTokenPaid[account])).div(1e18).add(rewards[account]); } function getRewardForDuration() external view returns (uint256) { return rewardRate.mul(rewardsDuration); } /** @dev It emits a `Staked` event. */ function stake(uint256 amount) external { _notPaused(); _updateReward(msg.sender); uint256 newBalance = _balances[msg.sender].add(amount); require(amount > 0, "R:ZERO_STAKE"); require(stakingToken.custodyAllowance(msg.sender, address(this)) >= newBalance, "R:INSUF_CUST_ALLOWANCE"); _totalSupply = _totalSupply.add(amount); _balances[msg.sender] = newBalance; emit Staked(msg.sender, amount); } /** @dev It emits a `Withdrawn` event. */ function withdraw(uint256 amount) public { _notPaused(); _updateReward(msg.sender); require(amount > 0, "R:ZERO_WITHDRAW"); _totalSupply = _totalSupply.sub(amount); _balances[msg.sender] = _balances[msg.sender].sub(amount); stakingToken.transferByCustodian(msg.sender, msg.sender, amount); emit Withdrawn(msg.sender, amount); } /** @dev It emits a `RewardPaid` event if any rewards are received. */ function getReward() public { _notPaused(); _updateReward(msg.sender); uint256 reward = rewards[msg.sender]; if (reward == uint256(0)) return; rewards[msg.sender] = uint256(0); rewardsToken.safeTransfer(msg.sender, reward); emit RewardPaid(msg.sender, reward); } function exit() external { withdraw(_balances[msg.sender]); getReward(); } /** @dev Only the contract Owner may call this. @dev It emits a `RewardAdded` event. */ function notifyRewardAmount(uint256 reward) external onlyOwner { _updateReward(address(0)); uint256 _rewardRate = block.timestamp >= periodFinish ? reward.div(rewardsDuration) : reward.add( periodFinish.sub(block.timestamp).mul(rewardRate) ).div(rewardsDuration); rewardRate = _rewardRate; // Ensure the provided reward amount is not more than the balance in the contract. // This keeps the reward rate in the right range, preventing overflows due to // very high values of rewardRate in the earned and rewardsPerToken functions; // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow. uint256 balance = rewardsToken.balanceOf(address(this)); require(_rewardRate <= balance.div(rewardsDuration), "R:REWARD_TOO_HIGH"); lastUpdateTime = block.timestamp; periodFinish = block.timestamp.add(rewardsDuration); emit RewardAdded(reward); } /** @dev End rewards emission earlier. Only the contract Owner may call this. */ function updatePeriodFinish(uint256 timestamp) external onlyOwner { _updateReward(address(0)); periodFinish = timestamp; } /** @dev Added to support recovering tokens unintentionally sent to this contract. Only the contract Owner may call this. @dev It emits a `Recovered` event. */ function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner { IERC20(tokenAddress).safeTransfer(owner(), tokenAmount); emit Recovered(tokenAddress, tokenAmount); } /** @dev Only the contract Owner may call this. @dev It emits a `RewardsDurationUpdated` event. */ function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner { require(block.timestamp > periodFinish, "R:PERIOD_NOT_FINISHED"); rewardsDuration = _rewardsDuration; emit RewardsDurationUpdated(rewardsDuration); } /** @dev Change the paused state of the contract. Only the contract Owner may call this. @dev It emits a `PauseChanged` event. */ function setPaused(bool _paused) external onlyOwner { // Ensure we're actually changing the state before we do anything require(_paused != paused, "R:ALREADY_SET"); // Set our paused state. paused = _paused; // If applicable, set the last pause time. if (_paused) lastPauseTime = block.timestamp; // Let everyone know that our pause state has changed. emit PauseChanged(paused); } } {"mode":"full","isActive":false}
違いを見つける