Diff
checker
Testo
Testo
Immagini
Documenti
Excel
Cartelle
Legal
Enterprise
Applicazione per desktop
Prezzi
Accedi
Scarica Diffchecker Desktop
Confronta il testo
Trova la differenza tra due file di testo
Strumenti
Cronologia
Editor live
Nascondi spazi bianchi
Comprimi invariate
Senza a capo
Layout
Diviso
Unificato
Livello di dettaglio
Intelligente
Parola
Carattere
Stili testo
Modifica aspetto
Evidenziazione sintassi
Scegli sintassi
Ignora
Trasforma testo
Vai alla prima modifica
Modifica input
Diffchecker Desktop
Il modo più sicuro per usare Diffchecker. Ottieni l'app Diffchecker Desktop: i tuoi diff non lasciano mai il tuo computer!
Ottieni Desktop
synthetix_maple_liquidity_mining_diff
Creato
5 anni fa
Il diff non scade mai
Eliminare
Esporta
Condividere
Spiegare
106 rimozioni
Linee
Totale
Rimosso
Caratteri
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
177 linee
Copia tutti
146 aggiunte
Linee
Totale
Aggiunto
Caratteri
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
215 linee
Copia tutti
Copia
Copiato
Copia
Copiato
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";
Copia
Copiato
Copia
Copiato
// 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";
Copia
Copiato
Copia
Copiato
import "./interfaces/IERC2258.sol";
// https://docs.synthetix.io/contracts/source/contracts/stakingrewards
// https://docs.synthetix.io/contracts/source/contracts/stakingrewards
Copia
Copiato
Copia
Copiato
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;
Copia
Copiato
Copia
Copiato
/* ========== STATE VARIABLES ========== */
IERC20 public immutable rewardsToken;
IERC2258 public immutable stakingToken;
Copia
Copiato
Copia
Copiato
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;
Copia
Copiato
Copia
Copiato
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;
Copia
Copiato
Copia
Copiato
mapping(address => uint256) private _balances;
mapping(address => uint256) private _balances;
Copia
Copiato
Copia
Copiato
/* ========== 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);
Copia
Copiato
Copia
Copiato
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
;
}
}
Copia
Copiato
Copia
Copiato
/* ========== 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) {
Copia
Copiato
Copia
Copiato
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);
}
}
Copia
Copiato
Copia
Copiato
/*
========== 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);
}
}
Copia
Copiato
Copia
Copiato
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);
Copia
Copiato
Copia
Copiato
stakingToken.
safeTransfer
(msg.sender,
amount);
stakingToken.
transferByCustodian
(msg.sender,
msg.sender,
amount);
emit Withdrawn(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
}
Copia
Copiato
Copia
Copiato
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];
Copia
Copiato
Copia
Copiato
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();
}
}
Copia
Copiato
Copia
Copiato
/* ========== 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));
Copia
Copiato
Copia
Copiato
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.
Copia
Copiato
Copia
Copiato
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;
Copia
Copiato
Copia
Copiato
periodFinish
= block.timestamp.add(rewardsDuration);
periodFinish
= block.timestamp.add(rewardsDuration);
emit RewardAdded(reward);
emit RewardAdded(reward);
}
}
Copia
Copiato
Copia
Copiato
/
/
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;
}
}
Copia
Copiato
Copia
Copiato
/
/
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 {
Copia
Copiato
Copia
Copiato
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);
}
}
Copia
Copiato
Copia
Copiato
/**
@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 {
Copia
Copiato
Copia
Copiato
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);
}
}
Copia
Copiato
Copia
Copiato
/* ========== 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");
Copia
Copiato
Copia
Copiato
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);
}
}
Copia
Copiato
Copia
Copiato
/* ========== 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);
}
}
Copia
Copiato
Copia
Copiato
{"mode":"full","isActive":false}
Diff salvati
Testo originale
Apri file
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); }
Testo modificato
Apri file
// 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}
Trovare la differenza