Diff
checker
Texte
Texte
Images
Documents
Excel
Dossiers
Legal
Enterprise
Application de bureau
Prix
Se connecter
Télécharger Diffchecker Desktop
Comparer le texte
Trouver la différence entre deux fichiers texte
Outils
Historique
Éditeur live
Cacher identiques
Sans retour à la ligne
Vue
Divisé
Unifié
Niveau de précision
Intelligent
Mot
Caractère
Coloration syntaxique
Choisir la syntaxe
Ignorer
Transformer le texte
Aller au premier écart
Modifier l'entrée
Diffchecker Desktop
La façon la plus sécurisée d'utiliser Diffchecker. Obtenez l'application Diffchecker Desktop : vos diffs ne quittent jamais votre ordinateur !
Obtenir Desktop
NYAN vs. APE
Créé
il y a 5 ans
Le diff n'expire jamais
Effacer
Exporter
Partager
Expliquer
2 suppressions
Lignes
Total
Supprimé
Caractères
Total
Supprimé
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
277 lignes
Copier tout
48 ajouts
Lignes
Total
Ajouté
Caractères
Total
Ajouté
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
318 lignes
Copier tout
Copier
Copié
Copier
Copié
/**
*Submitted for verification at arbiscan.io on 2021-09-13
*/
/**
/**
*Submitted for verification at arbiscan.io on 2021-09-08
*Submitted for verification at arbiscan.io on 2021-09-08
*/
*/
//SPDX-License-Identifier: MIT
//SPDX-License-Identifier: MIT
// File: @openzeppelin/contracts/ownership/Ownable.sol
// File: @openzeppelin/contracts/ownership/Ownable.sol
pragma solidity ^0.8.7;
pragma solidity ^0.8.7;
/**
/**
* @dev Contract module which provides a basic access control mechanism, where
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
* specific functions.
*
*
* This module is used through inheritance. It will make available the modifier
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
* the owner.
*/
*/
contract Ownable {
contract Ownable {
address public owner;
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
constructor() {
owner = msg.sender;
owner = msg.sender;
}
}
/**
/**
* @dev Throws if called by any account other than the owner.
* @dev Throws if called by any account other than the owner.
*/
*/
modifier onlyOwner() {
modifier onlyOwner() {
require(msg.sender == owner, "Ownable: caller is not the owner");
require(msg.sender == owner, "Ownable: caller is not the owner");
_;
_;
}
}
/**
/**
* @dev Leaves the contract without owner. It will not be possible to call
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
* thereby removing any functionality that is only available to the owner.
*/
*/
function renounceOwnership() public onlyOwner {
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(owner, address(0));
emit OwnershipTransferred(owner, address(0));
owner = address(0);
owner = address(0);
}
}
/**
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
* Can only be called by the current owner.
*/
*/
function transferOwnership(address newOwner) public onlyOwner {
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
_transferOwnership(newOwner);
}
}
/**
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
*/
function _transferOwnership(address newOwner) internal {
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(owner, newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
owner = newOwner;
}
}
}
}
interface IERC20 {
interface IERC20 {
function totalSupply() external view returns (uint256);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
}
Copier
Copié
Copier
Copié
contract StakedTokenWrapper {
contract StakedTokenWrapper {
uint256 public totalSupply;
uint256 public totalSupply;
Copier
Copié
Copier
Copié
uint128 public buyback = 2; //%
mapping(address => uint256) private _balances;
mapping(address => uint256) private _balances;
IERC20 public stakedToken;
IERC20 public stakedToken;
event Staked(address indexed user, uint256 amount);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
Copier
Copié
Copier
Copié
address public beneficiary = address(0x0398C40b50B4db0F76F1bc9C33403D17D005dA36);
function balanceOf(address account) public view returns (uint256) {
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
return _balances[account];
}
}
Copier
Copié
Copier
Copié
string constant _transferErrorMessage = "staked token transfer failed";
string constant _transferErrorMessage = "staked token transfer failed";
function stakeFor(address forWhom, uint128 amount) public payable virtual {
function stakeFor(address forWhom, uint128 amount) public payable virtual {
IERC20 st = stakedToken;
IERC20 st = stakedToken;
if(st == IERC20(address(0))) { //eth
if(st == IERC20(address(0))) { //eth
unchecked {
unchecked {
totalSupply += msg.value;
totalSupply += msg.value;
_balances[forWhom] += msg.value;
_balances[forWhom] += msg.value;
}
}
}
}
else {
else {
require(msg.value == 0, "non-zero eth");
require(msg.value == 0, "non-zero eth");
require(amount > 0, "Cannot stake 0");
require(amount > 0, "Cannot stake 0");
require(st.transferFrom(msg.sender, address(this), amount), _transferErrorMessage);
require(st.transferFrom(msg.sender, address(this), amount), _transferErrorMessage);
unchecked {
unchecked {
totalSupply += amount;
totalSupply += amount;
_balances[forWhom] += amount;
_balances[forWhom] += amount;
}
}
}
}
emit Staked(forWhom, amount);
emit Staked(forWhom, amount);
}
}
Copier
Copié
Copier
Copié
function withdraw(uint128 amount) public virtual {
function withdraw(uint128 amount) public virtual {
require(amount <= _balances[msg.sender], "withdraw: balance is lower");
require(amount <= _balances[msg.sender], "withdraw: balance is lower");
unchecked {
unchecked {
_balances[msg.sender] -= amount;
_balances[msg.sender] -= amount;
totalSupply = totalSupply-amount;
totalSupply = totalSupply-amount;
}
}
IERC20 st = stakedToken;
IERC20 st = stakedToken;
if(st == IERC20(address(0))) { //eth
if(st == IERC20(address(0))) { //eth
Copier
Copié
Copier
Copié
(bool success
, ) = msg.sender.call{value: amount
}("");
require(success
, "eth transfer failure");
uint128 val = (amount*buyback)/100;
beneficiary.call{value: val}("");
(bool success
_
, ) = msg.sender.call{value: amount
-val
}("");
require(success
_
, "eth transfer failure");
}
}
else {
else {
require(stakedToken.transfer(msg.sender, amount), _transferErrorMessage);
require(stakedToken.transfer(msg.sender, amount), _transferErrorMessage);
}
}
emit Withdrawn(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
}
}
}
Copier
Copié
Copier
Copié
contract
NyanRewards
is StakedTokenWrapper, Ownable {
contract
ApeRewardsETH
is StakedTokenWrapper, Ownable {
IERC20 public rewardToken;
IERC20 public rewardToken;
uint256 public rewardRate;
uint256 public rewardRate;
uint64 public periodFinish;
uint64 public periodFinish;
uint64 public lastUpdateTime;
uint64 public lastUpdateTime;
uint128 public rewardPerTokenStored;
uint128 public rewardPerTokenStored;
Copier
Copié
Copier
Copié
struct UserRewards {
struct UserRewards {
uint128 userRewardPerTokenPaid;
uint128 userRewardPerTokenPaid;
uint128 rewards;
uint128 rewards;
}
}
mapping(address => UserRewards) public userRewards;
mapping(address => UserRewards) public userRewards;
event RewardAdded(uint256 reward);
event RewardAdded(uint256 reward);
event RewardPaid(address indexed user, uint256 reward);
event RewardPaid(address indexed user, uint256 reward);
Copier
Copié
Copier
Copié
uint256 public maxStakingAmount = 2 * 10**0 * 10**17 ; //0.2 ETH
constructor(IERC20 _rewardToken, IERC20 _stakedToken) {
constructor(IERC20 _rewardToken, IERC20 _stakedToken) {
rewardToken = _rewardToken;
rewardToken = _rewardToken;
stakedToken = _stakedToken;
stakedToken = _stakedToken;
}
}
modifier updateReward(address account) {
modifier updateReward(address account) {
uint128 _rewardPerTokenStored = rewardPerToken();
uint128 _rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
lastUpdateTime = lastTimeRewardApplicable();
rewardPerTokenStored = _rewardPerTokenStored;
rewardPerTokenStored = _rewardPerTokenStored;
userRewards[account].rewards = earned(account);
userRewards[account].rewards = earned(account);
userRewards[account].userRewardPerTokenPaid = _rewardPerTokenStored;
userRewards[account].userRewardPerTokenPaid = _rewardPerTokenStored;
_;
_;
}
}
function lastTimeRewardApplicable() public view returns (uint64) {
function lastTimeRewardApplicable() public view returns (uint64) {
uint64 blockTimestamp = uint64(block.timestamp);
uint64 blockTimestamp = uint64(block.timestamp);
return blockTimestamp < periodFinish ? blockTimestamp : periodFinish;
return blockTimestamp < periodFinish ? blockTimestamp : periodFinish;
}
}
function rewardPerToken() public view returns (uint128) {
function rewardPerToken() public view returns (uint128) {
uint256 totalStakedSupply = totalSupply;
uint256 totalStakedSupply = totalSupply;
if (totalStakedSupply == 0) {
if (totalStakedSupply == 0) {
return rewardPerTokenStored;
return rewardPerTokenStored;
}
}
unchecked {
unchecked {
uint256 rewardDuration = lastTimeRewardApplicable()-lastUpdateTime;
uint256 rewardDuration = lastTimeRewardApplicable()-lastUpdateTime;
return uint128(rewardPerTokenStored + rewardDuration*rewardRate*1e18/totalStakedSupply);
return uint128(rewardPerTokenStored + rewardDuration*rewardRate*1e18/totalStakedSupply);
}
}
}
}
function earned(address account) public view returns (uint128) {
function earned(address account) public view returns (uint128) {
unchecked {
unchecked {
return uint128(balanceOf(account)*(rewardPerToken()-userRewards[account].userRewardPerTokenPaid)/1e18 + userRewards[account].rewards);
return uint128(balanceOf(account)*(rewardPerToken()-userRewards[account].userRewardPerTokenPaid)/1e18 + userRewards[account].rewards);
}
}
}
}
function stake(uint128 amount) external payable {
function stake(uint128 amount) external payable {
Copier
Copié
Copier
Copié
require(amount < maxStakingAmount, "amount exceed max staking amount");
stakeFor(msg.sender, amount);
stakeFor(msg.sender, amount);
}
}
function stakeFor(address forWhom, uint128 amount) public payable override updateReward(forWhom) {
function stakeFor(address forWhom, uint128 amount) public payable override updateReward(forWhom) {
super.stakeFor(forWhom, amount);
super.stakeFor(forWhom, amount);
}
}
function withdraw(uint128 amount) public override updateReward(msg.sender) {
function withdraw(uint128 amount) public override updateReward(msg.sender) {
Copier
Copié
Copier
Copié
super.withdraw(amount);
super.withdraw(amount);
}
}
function exit() external {
function exit() external {
getReward();
getReward();
withdraw(uint128(balanceOf(msg.sender)));
withdraw(uint128(balanceOf(msg.sender)));
}
}
function getReward() public updateReward(msg.sender) {
function getReward() public updateReward(msg.sender) {
uint256 reward = earned(msg.sender);
uint256 reward = earned(msg.sender);
if (reward > 0) {
if (reward > 0) {
userRewards[msg.sender].rewards = 0;
userRewards[msg.sender].rewards = 0;
require(rewardToken.transfer(msg.sender, reward), "reward transfer failed");
require(rewardToken.transfer(msg.sender, reward), "reward transfer failed");
emit RewardPaid(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
}
}
function setRewardParams(uint128 reward, uint64 duration) external onlyOwner {
function setRewardParams(uint128 reward, uint64 duration) external onlyOwner {
unchecked {
unchecked {
require(reward > 0);
require(reward > 0);
rewardPerTokenStored = rewardPerToken();
rewardPerTokenStored = rewardPerToken();
uint64 blockTimestamp = uint64(block.timestamp);
uint64 blockTimestamp = uint64(block.timestamp);
uint256 maxRewardSupply = rewardToken.balanceOf(address(this));
uint256 maxRewardSupply = rewardToken.balanceOf(address(this));
if(rewardToken == stakedToken)
if(rewardToken == stakedToken)
maxRewardSupply -= totalSupply;
maxRewardSupply -= totalSupply;
uint256 leftover = 0;
uint256 leftover = 0;
if (blockTimestamp >= periodFinish) {
if (blockTimestamp >= periodFinish) {
rewardRate = reward/duration;
rewardRate = reward/duration;
} else {
} else {
uint256 remaining = periodFinish-blockTimestamp;
uint256 remaining = periodFinish-blockTimestamp;
leftover = remaining*rewardRate;
leftover = remaining*rewardRate;
rewardRate = (reward+leftover)/duration;
rewardRate = (reward+leftover)/duration;
}
}
require(reward+leftover <= maxRewardSupply, "not enough tokens");
require(reward+leftover <= maxRewardSupply, "not enough tokens");
lastUpdateTime = blockTimestamp;
lastUpdateTime = blockTimestamp;
periodFinish = blockTimestamp+duration;
periodFinish = blockTimestamp+duration;
emit RewardAdded(reward);
emit RewardAdded(reward);
}
}
}
}
function withdrawReward() external onlyOwner {
function withdrawReward() external onlyOwner {
uint256 rewardSupply = rewardToken.balanceOf(address(this));
uint256 rewardSupply = rewardToken.balanceOf(address(this));
//ensure funds staked by users can't be transferred out
//ensure funds staked by users can't be transferred out
if(rewardToken == stakedToken)
if(rewardToken == stakedToken)
rewardSupply -= totalSupply;
rewardSupply -= totalSupply;
require(rewardToken.transfer(msg.sender, rewardSupply));
require(rewardToken.transfer(msg.sender, rewardSupply));
rewardRate = 0;
rewardRate = 0;
periodFinish = uint64(block.timestamp);
periodFinish = uint64(block.timestamp);
}
}
Copier
Copié
Copier
Copié
function setMaxStakingAmount(uint256 value) external onlyOwner {
require(value > 0);
maxStakingAmount = value;
}
function setBuyback(uint128 value) external onlyOwner {
buyback = value;
}
function setBuyBackAddr(address addr) external onlyOwner {
beneficiary = addr;
}
}
}
/*
/*
____ __ __ __ _
____ __ __ __ _
/ __/__ __ ___ / /_ / / ___ / /_ (_)__ __
/ __/__ __ ___ / /_ / / ___ / /_ (_)__ __
_\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
_\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
/___/
/___/
* Synthetix: YFIRewards.sol
* Synthetix: YFIRewards.sol
*
*
* Docs: https://docs.synthetix.io/
* Docs: https://docs.synthetix.io/
*
*
*
*
* MIT License
* MIT License
* ===========
* ===========
*
*
* Copyright (c) 2020 Synthetix
* Copyright (c) 2020 Synthetix
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in all
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/
*/
Différences enregistrées
Texte d'origine
Ouvrir un fichier
/** *Submitted for verification at arbiscan.io on 2021-09-08 */ //SPDX-License-Identifier: MIT // File: @openzeppelin/contracts/ownership/Ownable.sol pragma solidity ^0.8.7; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor() { owner = msg.sender; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner, "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(owner, address(0)); owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } } interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } contract StakedTokenWrapper { uint256 public totalSupply; mapping(address => uint256) private _balances; IERC20 public stakedToken; event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); function balanceOf(address account) public view returns (uint256) { return _balances[account]; } string constant _transferErrorMessage = "staked token transfer failed"; function stakeFor(address forWhom, uint128 amount) public payable virtual { IERC20 st = stakedToken; if(st == IERC20(address(0))) { //eth unchecked { totalSupply += msg.value; _balances[forWhom] += msg.value; } } else { require(msg.value == 0, "non-zero eth"); require(amount > 0, "Cannot stake 0"); require(st.transferFrom(msg.sender, address(this), amount), _transferErrorMessage); unchecked { totalSupply += amount; _balances[forWhom] += amount; } } emit Staked(forWhom, amount); } function withdraw(uint128 amount) public virtual { require(amount <= _balances[msg.sender], "withdraw: balance is lower"); unchecked { _balances[msg.sender] -= amount; totalSupply = totalSupply-amount; } IERC20 st = stakedToken; if(st == IERC20(address(0))) { //eth (bool success, ) = msg.sender.call{value: amount}(""); require(success, "eth transfer failure"); } else { require(stakedToken.transfer(msg.sender, amount), _transferErrorMessage); } emit Withdrawn(msg.sender, amount); } } contract NyanRewards is StakedTokenWrapper, Ownable { IERC20 public rewardToken; uint256 public rewardRate; uint64 public periodFinish; uint64 public lastUpdateTime; uint128 public rewardPerTokenStored; struct UserRewards { uint128 userRewardPerTokenPaid; uint128 rewards; } mapping(address => UserRewards) public userRewards; event RewardAdded(uint256 reward); event RewardPaid(address indexed user, uint256 reward); constructor(IERC20 _rewardToken, IERC20 _stakedToken) { rewardToken = _rewardToken; stakedToken = _stakedToken; } modifier updateReward(address account) { uint128 _rewardPerTokenStored = rewardPerToken(); lastUpdateTime = lastTimeRewardApplicable(); rewardPerTokenStored = _rewardPerTokenStored; userRewards[account].rewards = earned(account); userRewards[account].userRewardPerTokenPaid = _rewardPerTokenStored; _; } function lastTimeRewardApplicable() public view returns (uint64) { uint64 blockTimestamp = uint64(block.timestamp); return blockTimestamp < periodFinish ? blockTimestamp : periodFinish; } function rewardPerToken() public view returns (uint128) { uint256 totalStakedSupply = totalSupply; if (totalStakedSupply == 0) { return rewardPerTokenStored; } unchecked { uint256 rewardDuration = lastTimeRewardApplicable()-lastUpdateTime; return uint128(rewardPerTokenStored + rewardDuration*rewardRate*1e18/totalStakedSupply); } } function earned(address account) public view returns (uint128) { unchecked { return uint128(balanceOf(account)*(rewardPerToken()-userRewards[account].userRewardPerTokenPaid)/1e18 + userRewards[account].rewards); } } function stake(uint128 amount) external payable { stakeFor(msg.sender, amount); } function stakeFor(address forWhom, uint128 amount) public payable override updateReward(forWhom) { super.stakeFor(forWhom, amount); } function withdraw(uint128 amount) public override updateReward(msg.sender) { super.withdraw(amount); } function exit() external { getReward(); withdraw(uint128(balanceOf(msg.sender))); } function getReward() public updateReward(msg.sender) { uint256 reward = earned(msg.sender); if (reward > 0) { userRewards[msg.sender].rewards = 0; require(rewardToken.transfer(msg.sender, reward), "reward transfer failed"); emit RewardPaid(msg.sender, reward); } } function setRewardParams(uint128 reward, uint64 duration) external onlyOwner { unchecked { require(reward > 0); rewardPerTokenStored = rewardPerToken(); uint64 blockTimestamp = uint64(block.timestamp); uint256 maxRewardSupply = rewardToken.balanceOf(address(this)); if(rewardToken == stakedToken) maxRewardSupply -= totalSupply; uint256 leftover = 0; if (blockTimestamp >= periodFinish) { rewardRate = reward/duration; } else { uint256 remaining = periodFinish-blockTimestamp; leftover = remaining*rewardRate; rewardRate = (reward+leftover)/duration; } require(reward+leftover <= maxRewardSupply, "not enough tokens"); lastUpdateTime = blockTimestamp; periodFinish = blockTimestamp+duration; emit RewardAdded(reward); } } function withdrawReward() external onlyOwner { uint256 rewardSupply = rewardToken.balanceOf(address(this)); //ensure funds staked by users can't be transferred out if(rewardToken == stakedToken) rewardSupply -= totalSupply; require(rewardToken.transfer(msg.sender, rewardSupply)); rewardRate = 0; periodFinish = uint64(block.timestamp); } } /* ____ __ __ __ _ / __/__ __ ___ / /_ / / ___ / /_ (_)__ __ _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ / /___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\ /___/ * Synthetix: YFIRewards.sol * * Docs: https://docs.synthetix.io/ * * * MIT License * =========== * * Copyright (c) 2020 Synthetix * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
Texte modifié
Ouvrir un fichier
/** *Submitted for verification at arbiscan.io on 2021-09-13 */ /** *Submitted for verification at arbiscan.io on 2021-09-08 */ //SPDX-License-Identifier: MIT // File: @openzeppelin/contracts/ownership/Ownable.sol pragma solidity ^0.8.7; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor() { owner = msg.sender; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner, "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(owner, address(0)); owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } } interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } contract StakedTokenWrapper { uint256 public totalSupply; uint128 public buyback = 2; //% mapping(address => uint256) private _balances; IERC20 public stakedToken; event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); address public beneficiary = address(0x0398C40b50B4db0F76F1bc9C33403D17D005dA36); function balanceOf(address account) public view returns (uint256) { return _balances[account]; } string constant _transferErrorMessage = "staked token transfer failed"; function stakeFor(address forWhom, uint128 amount) public payable virtual { IERC20 st = stakedToken; if(st == IERC20(address(0))) { //eth unchecked { totalSupply += msg.value; _balances[forWhom] += msg.value; } } else { require(msg.value == 0, "non-zero eth"); require(amount > 0, "Cannot stake 0"); require(st.transferFrom(msg.sender, address(this), amount), _transferErrorMessage); unchecked { totalSupply += amount; _balances[forWhom] += amount; } } emit Staked(forWhom, amount); } function withdraw(uint128 amount) public virtual { require(amount <= _balances[msg.sender], "withdraw: balance is lower"); unchecked { _balances[msg.sender] -= amount; totalSupply = totalSupply-amount; } IERC20 st = stakedToken; if(st == IERC20(address(0))) { //eth uint128 val = (amount*buyback)/100; beneficiary.call{value: val}(""); (bool success_, ) = msg.sender.call{value: amount-val}(""); require(success_, "eth transfer failure"); } else { require(stakedToken.transfer(msg.sender, amount), _transferErrorMessage); } emit Withdrawn(msg.sender, amount); } } contract ApeRewardsETH is StakedTokenWrapper, Ownable { IERC20 public rewardToken; uint256 public rewardRate; uint64 public periodFinish; uint64 public lastUpdateTime; uint128 public rewardPerTokenStored; struct UserRewards { uint128 userRewardPerTokenPaid; uint128 rewards; } mapping(address => UserRewards) public userRewards; event RewardAdded(uint256 reward); event RewardPaid(address indexed user, uint256 reward); uint256 public maxStakingAmount = 2 * 10**0 * 10**17 ; //0.2 ETH constructor(IERC20 _rewardToken, IERC20 _stakedToken) { rewardToken = _rewardToken; stakedToken = _stakedToken; } modifier updateReward(address account) { uint128 _rewardPerTokenStored = rewardPerToken(); lastUpdateTime = lastTimeRewardApplicable(); rewardPerTokenStored = _rewardPerTokenStored; userRewards[account].rewards = earned(account); userRewards[account].userRewardPerTokenPaid = _rewardPerTokenStored; _; } function lastTimeRewardApplicable() public view returns (uint64) { uint64 blockTimestamp = uint64(block.timestamp); return blockTimestamp < periodFinish ? blockTimestamp : periodFinish; } function rewardPerToken() public view returns (uint128) { uint256 totalStakedSupply = totalSupply; if (totalStakedSupply == 0) { return rewardPerTokenStored; } unchecked { uint256 rewardDuration = lastTimeRewardApplicable()-lastUpdateTime; return uint128(rewardPerTokenStored + rewardDuration*rewardRate*1e18/totalStakedSupply); } } function earned(address account) public view returns (uint128) { unchecked { return uint128(balanceOf(account)*(rewardPerToken()-userRewards[account].userRewardPerTokenPaid)/1e18 + userRewards[account].rewards); } } function stake(uint128 amount) external payable { require(amount < maxStakingAmount, "amount exceed max staking amount"); stakeFor(msg.sender, amount); } function stakeFor(address forWhom, uint128 amount) public payable override updateReward(forWhom) { super.stakeFor(forWhom, amount); } function withdraw(uint128 amount) public override updateReward(msg.sender) { super.withdraw(amount); } function exit() external { getReward(); withdraw(uint128(balanceOf(msg.sender))); } function getReward() public updateReward(msg.sender) { uint256 reward = earned(msg.sender); if (reward > 0) { userRewards[msg.sender].rewards = 0; require(rewardToken.transfer(msg.sender, reward), "reward transfer failed"); emit RewardPaid(msg.sender, reward); } } function setRewardParams(uint128 reward, uint64 duration) external onlyOwner { unchecked { require(reward > 0); rewardPerTokenStored = rewardPerToken(); uint64 blockTimestamp = uint64(block.timestamp); uint256 maxRewardSupply = rewardToken.balanceOf(address(this)); if(rewardToken == stakedToken) maxRewardSupply -= totalSupply; uint256 leftover = 0; if (blockTimestamp >= periodFinish) { rewardRate = reward/duration; } else { uint256 remaining = periodFinish-blockTimestamp; leftover = remaining*rewardRate; rewardRate = (reward+leftover)/duration; } require(reward+leftover <= maxRewardSupply, "not enough tokens"); lastUpdateTime = blockTimestamp; periodFinish = blockTimestamp+duration; emit RewardAdded(reward); } } function withdrawReward() external onlyOwner { uint256 rewardSupply = rewardToken.balanceOf(address(this)); //ensure funds staked by users can't be transferred out if(rewardToken == stakedToken) rewardSupply -= totalSupply; require(rewardToken.transfer(msg.sender, rewardSupply)); rewardRate = 0; periodFinish = uint64(block.timestamp); } function setMaxStakingAmount(uint256 value) external onlyOwner { require(value > 0); maxStakingAmount = value; } function setBuyback(uint128 value) external onlyOwner { buyback = value; } function setBuyBackAddr(address addr) external onlyOwner { beneficiary = addr; } } /* ____ __ __ __ _ / __/__ __ ___ / /_ / / ___ / /_ (_)__ __ _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ / /___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\ /___/ * Synthetix: YFIRewards.sol * * Docs: https://docs.synthetix.io/ * * * MIT License * =========== * * Copyright (c) 2020 Synthetix * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
Trouver la différence