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
TombBasedRewardPools
Créé
il y a 4 ans
Le diff n'expire jamais
Effacer
Exporter
Partager
Expliquer
77 suppressions
Lignes
Total
Supprimé
Caractères
Total
Supprimé
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
274 lignes
Copier tout
103 ajouts
Lignes
Total
Ajouté
Caractères
Total
Ajouté
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
299 lignes
Copier tout
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
Copier
Copié
Copier
Copié
pragma solidity
0.6.12
;
pragma solidity
^0.8.0
;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Copier
Copié
Copier
Copié
import "@openzeppelin/contracts/token/ERC20/
SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/
utils/
SafeERC20.sol";
import "@openzeppelin/contracts/
math/SafeMath.sol";
import "@openzeppelin/contracts/
utils/
math/SafeMath.sol";
Copier
Copié
Copier
Copié
// Note that this pool has no minter key of
t
SHARE (rewards).
// Note that this pool has no minter key of
b
SHARE (rewards).
// Instead, the governance will call
t
SHARE distributeReward method and send reward to this pool at the beginning.
// Instead, the governance will call
b
SHARE distributeReward method and send reward to this pool at the beginning.
contract
T
ShareRewardPool {
contract
B
ShareRewardPool {
using SafeMath for uint256;
using SafeMath for uint256;
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;
// governance
// governance
address public operator;
address public operator;
// Info of each user.
// Info of each user.
struct UserInfo {
struct UserInfo {
uint256 amount; // How many LP tokens the user has provided.
uint256 amount; // How many LP tokens the user has provided.
uint256 rewardDebt; // Reward debt. See explanation below.
uint256 rewardDebt; // Reward debt. See explanation below.
}
}
// Info of each pool.
// Info of each pool.
struct PoolInfo {
struct PoolInfo {
IERC20 token; // Address of LP token contract.
IERC20 token; // Address of LP token contract.
Copier
Copié
Copier
Copié
uint256 allocPoint; // How many allocation points assigned to this pool.
t
SHAREs to distribute per block.
uint256 allocPoint; // How many allocation points assigned to this pool.
b
SHAREs to distribute per block.
uint256 lastRewardTime; // Last time that
t
SHAREs distribution occurs.
uint256 lastRewardTime; // Last time that
b
SHAREs distribution occurs.
uint256 acc
T
SharePerShare; // Accumulated
t
SHAREs per share, times 1e18. See below.
uint256 acc
B
SharePerShare; // Accumulated
b
SHAREs per share, times 1e18. See below.
bool isStarted; // if lastRewardTime has passed
bool isStarted; // if lastRewardTime has passed
}
}
Copier
Copié
Copier
Copié
IERC20 public
t
share;
IERC20 public
b
share;
// Info of each pool.
// Info of each pool.
PoolInfo[] public poolInfo;
PoolInfo[] public poolInfo;
// Info of each user that stakes LP tokens.
// Info of each user that stakes LP tokens.
mapping(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;
Copier
Copié
Copier
Copié
// The time when
t
SHARE mining starts.
// The time when
b
SHARE mining starts.
uint256 public poolStartTime;
uint256 public poolStartTime;
Copier
Copié
Copier
Copié
// The time when
t
SHARE mining ends.
// The time when
b
SHARE mining ends.
uint256 public poolEndTime;
uint256 public poolEndTime;
Copier
Copié
Copier
Copié
uint256 public
t
SharePerSecond = 0.
00186122
ether; //
59500 t
share / (
370
days * 24h * 60min * 60s)
address public daoFundAddress;
uint256 public runningTime =
370
days; //
370
days
uint256 public constant TOTAL_REWARDS =
59500
ether;
uint256 public
b
SharePerSecond = 0.
003486
ether; //
50000 b
share / (
166
days * 24h * 60min * 60s)
uint256 public runningTime =
166
days; //
166
days
uint256 public constant TOTAL_REWARDS =
50000
ether;
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);
event RewardPaid(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 amount);
constructor(
constructor(
Copier
Copié
Copier
Copié
address _
t
share,
address _
b
share,
address _daoFund,
uint256 _poolStartTime
uint256 _poolStartTime
Copier
Copié
Copier
Copié
)
public
{
)
{
require(block.timestamp < _poolStartTime, "
late
");
require(block.timestamp < _poolStartTime, "
pool cant be started in the past
");
if (_
t
share != address(0))
t
share = IERC20(_
t
share);
if (_
b
share != address(0))
b
share = IERC20(_
b
share);
if(_daoFund != address(0)) daoFundAddress = _daoFund;
poolStartTime = _poolStartTime;
poolStartTime = _poolStartTime;
poolEndTime = poolStartTime + runningTime;
poolEndTime = poolStartTime + runningTime;
operator = msg.sender;
operator = msg.sender;
}
}
modifier onlyOperator() {
modifier onlyOperator() {
Copier
Copié
Copier
Copié
require(operator == msg.sender, "
T
ShareRewardPool: caller is not the operator");
require(operator == msg.sender, "
B
ShareRewardPool: caller is not the operator");
_;
_;
}
}
function checkPoolDuplicate(IERC20 _token) internal view {
function checkPoolDuplicate(IERC20 _token) internal view {
uint256 length = poolInfo.length;
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
for (uint256 pid = 0; pid < length; ++pid) {
Copier
Copié
Copier
Copié
require(poolInfo[pid].token != _token, "
T
ShareRewardPool: existing pool?");
require(poolInfo[pid].token != _token, "
B
ShareRewardPool: existing pool?");
}
}
}
}
Copier
Copié
Copier
Copié
// Add
a
new lp to the pool. Can only be called by
the owner
.
// Add
new lp to the pool. Can only be called by
operator
.
function add(
function add(
uint256 _allocPoint,
uint256 _allocPoint,
IERC20 _token,
IERC20 _token,
bool _withUpdate,
bool _withUpdate,
uint256 _lastRewardTime
uint256 _lastRewardTime
) public onlyOperator {
) public onlyOperator {
checkPoolDuplicate(_token);
checkPoolDuplicate(_token);
if (_withUpdate) {
if (_withUpdate) {
massUpdatePools();
massUpdatePools();
}
}
if (block.timestamp < poolStartTime) {
if (block.timestamp < poolStartTime) {
// chef is sleeping
// chef is sleeping
if (_lastRewardTime == 0) {
if (_lastRewardTime == 0) {
_lastRewardTime = poolStartTime;
_lastRewardTime = poolStartTime;
} else {
} else {
if (_lastRewardTime < poolStartTime) {
if (_lastRewardTime < poolStartTime) {
_lastRewardTime = poolStartTime;
_lastRewardTime = poolStartTime;
}
}
}
}
} else {
} else {
// chef is cooking
// chef is cooking
if (_lastRewardTime == 0 || _lastRewardTime < block.timestamp) {
if (_lastRewardTime == 0 || _lastRewardTime < block.timestamp) {
_lastRewardTime = block.timestamp;
_lastRewardTime = block.timestamp;
}
}
}
}
Copier
Copié
Copier
Copié
bool _isStarted =
bool _isStarted =
(_lastRewardTime <= poolStartTime) ||
(_lastRewardTime <= block.timestamp);
(_lastRewardTime <= poolStartTime) ||
(_lastRewardTime <= block.timestamp);
poolInfo.push(PoolInfo({
poolInfo.push(PoolInfo({
Copier
Copié
Copier
Copié
token
: _token,
token
: _token,
allocPoint
: _allocPoint,
allocPoint
: _allocPoint,
lastRewardTime
: _lastRewardTime,
lastRewardTime
: _lastRewardTime,
acc
T
SharePerShare
: 0,
acc
B
SharePerShare
: 0,
isStarted
: _isStarted
isStarted
: _isStarted
}));
}));
if (_isStarted) {
if (_isStarted) {
totalAllocPoint = totalAllocPoint.add(_allocPoint);
totalAllocPoint = totalAllocPoint.add(_allocPoint);
}
}
}
}
Copier
Copié
Copier
Copié
// Update the given pool's
t
SHARE allocation point. Can only be called by the
owner.
// starting allocations for our pools
// BASED-TOMB LP: 21500 $BSHARE
// BSHARE-TOMB LP: 21000 $BSHARE
// TEAM: 4500 $BSHARE
// CURVE STABLES LP (OR GEIST STABLES LP): 3000 $BSHARE
// Update the given pool's
b
SHARE allocation point. Can only be called by the
operator.
// @allocPoints for TEAM can NOT be altered after added - PID 2
// @allocPoints for main LP pools can NOT be smaller than 12,000
function set(uint256 _pid, uint256 _allocPoint) public onlyOperator {
function set(uint256 _pid, uint256 _allocPoint) public onlyOperator {
massUpdatePools();
massUpdatePools();
Copier
Copié
Copier
Copié
require (_pid != 2, "CAN NOT ADJUST TEAM ALLOCATIONS");
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
Copier
Copié
Copier
Copié
if (pool.isStarted) {
totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add(
if (_pid == 0 || _pid == 1) {
_allocPoint
require(_allocPoint >= 12000 * 10**18, "out of range"); // >= allocations for lp pools cant be less than 12,000
);
if (pool.isStarted) {
totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add(
_allocPoint);
}
} else if (_pid > 2) {
if (pool.isStarted) {
totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add(
_allocPoint
);
}
}
}
pool.allocPoint = _allocPoint;
pool.allocPoint = _allocPoint;
}
}
// Return accumulate rewards over the given _from to _to block.
// Return accumulate rewards over the given _from to _to block.
function getGeneratedReward(uint256 _fromTime, uint256 _toTime) public view returns (uint256) {
function getGeneratedReward(uint256 _fromTime, uint256 _toTime) public view returns (uint256) {
if (_fromTime >= _toTime) return 0;
if (_fromTime >= _toTime) return 0;
if (_toTime >= poolEndTime) {
if (_toTime >= poolEndTime) {
if (_fromTime >= poolEndTime) return 0;
if (_fromTime >= poolEndTime) return 0;
Copier
Copié
Copier
Copié
if (_fromTime <= poolStartTime) return poolEndTime.sub(poolStartTime).mul(
t
SharePerSecond);
if (_fromTime <= poolStartTime) return poolEndTime.sub(poolStartTime).mul(
b
SharePerSecond);
return poolEndTime.sub(_fromTime).mul(
t
SharePerSecond);
return poolEndTime.sub(_fromTime).mul(
b
SharePerSecond);
} else {
} else {
if (_toTime <= poolStartTime) return 0;
if (_toTime <= poolStartTime) return 0;
Copier
Copié
Copier
Copié
if (_fromTime <= poolStartTime) return _toTime.sub(poolStartTime).mul(
t
SharePerSecond);
if (_fromTime <= poolStartTime) return _toTime.sub(poolStartTime).mul(
b
SharePerSecond);
return _toTime.sub(_fromTime).mul(
t
SharePerSecond);
return _toTime.sub(_fromTime).mul(
b
SharePerSecond);
}
}
}
}
Copier
Copié
Copier
Copié
// View function to see pending
t
SHAREs on frontend.
// View function to see pending
b
SHAREs on frontend.
function pendingShare(uint256 _pid, address _user) external view returns (uint256) {
function pendingShare(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];
Copier
Copié
Copier
Copié
uint256 acc
T
SharePerShare = pool.acc
T
SharePerShare;
uint256 acc
B
SharePerShare = pool.acc
B
SharePerShare;
uint256 tokenSupply = pool.token.balanceOf(address(this));
uint256 tokenSupply = pool.token.balanceOf(address(this));
if (block.timestamp > pool.lastRewardTime && tokenSupply != 0) {
if (block.timestamp > pool.lastRewardTime && tokenSupply != 0) {
uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp);
uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp);
Copier
Copié
Copier
Copié
uint256 _
t
shareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint);
uint256 _
b
shareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint);
acc
T
SharePerShare = acc
T
SharePerShare.add(_
t
shareReward.mul(1e18).div(tokenSupply));
acc
B
SharePerShare = acc
B
SharePerShare.add(_
b
shareReward.mul(1e18).div(tokenSupply));
}
}
Copier
Copié
Copier
Copié
return user.amount.mul(acc
T
SharePerShare).div(1e18).sub(user.rewardDebt);
return user.amount.mul(acc
B
SharePerShare).div(1e18).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.timestamp <= pool.lastRewardTime) {
if (block.timestamp <= pool.lastRewardTime) {
return;
return;
}
}
uint256 tokenSupply = pool.token.balanceOf(address(this));
uint256 tokenSupply = pool.token.balanceOf(address(this));
if (tokenSupply == 0) {
if (tokenSupply == 0) {
pool.lastRewardTime = block.timestamp;
pool.lastRewardTime = block.timestamp;
return;
return;
}
}
if (!pool.isStarted) {
if (!pool.isStarted) {
pool.isStarted = true;
pool.isStarted = true;
totalAllocPoint = totalAllocPoint.add(pool.allocPoint);
totalAllocPoint = totalAllocPoint.add(pool.allocPoint);
}
}
if (totalAllocPoint > 0) {
if (totalAllocPoint > 0) {
uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp);
uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp);
Copier
Copié
Copier
Copié
uint256 _
t
shareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint);
uint256 _
b
shareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint);
pool.acc
T
SharePerShare = pool.acc
T
SharePerShare.add(_
t
shareReward.mul(1e18).div(tokenSupply));
pool.acc
B
SharePerShare = pool.acc
B
SharePerShare.add(_
b
shareReward.mul(1e18).div(tokenSupply));
}
}
pool.lastRewardTime = block.timestamp;
pool.lastRewardTime = block.timestamp;
}
}
// Deposit LP tokens.
// Deposit LP tokens.
function deposit(uint256 _pid, uint256 _amount) public {
function deposit(uint256 _pid, uint256 _amount) public {
address _sender = msg.sender;
address _sender = msg.sender;
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_sender];
UserInfo storage user = userInfo[_pid][_sender];
updatePool(_pid);
updatePool(_pid);
if (user.amount > 0) {
if (user.amount > 0) {
Copier
Copié
Copier
Copié
uint256 _pending = user.amount.mul(pool.acc
T
SharePerShare).div(1e18).sub(user.rewardDebt);
uint256 _pending = user.amount.mul(pool.acc
B
SharePerShare).div(1e18).sub(user.rewardDebt);
if (_pending > 0) {
if (_pending > 0) {
Copier
Copié
Copier
Copié
safe
T
ShareTransfer(_sender, _pending);
safe
B
ShareTransfer(_sender, _pending);
emit RewardPaid(_sender, _pending);
emit RewardPaid(_sender, _pending);
}
}
}
}
Copier
Copié
Copier
Copié
if (_amount > 0
) {
if (_amount > 0
&& _pid > 2) {
pool.token.safeTransferFrom(_sender, address(this), _amount);
uint256 depositDebt = _amount.mul(20).div(10000);
user.amount = user.amount.add(_amount.sub(depositDebt));
pool.token.safeTransfer(daoFundAddress, depositDebt);
} else if (_amount > 0 && _pid <= 2) {
pool.token.safeTransferFrom(_sender, address(this), _amount);
pool.token.safeTransferFrom(_sender, address(this), _amount);
user.amount = user.amount.add(_amount);
user.amount = user.amount.add(_amount);
}
}
Copier
Copié
Copier
Copié
user.rewardDebt = user.amount.mul(pool.acc
T
SharePerShare).div(1e18);
user.rewardDebt = user.amount.mul(pool.acc
B
SharePerShare).div(1e18);
emit Deposit(_sender, _pid, _amount);
emit Deposit(_sender, _pid, _amount);
}
}
// Withdraw LP tokens.
// Withdraw LP tokens.
function withdraw(uint256 _pid, uint256 _amount) public {
function withdraw(uint256 _pid, uint256 _amount) public {
address _sender = msg.sender;
address _sender = msg.sender;
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_sender];
UserInfo storage user = userInfo[_pid][_sender];
require(user.amount >= _amount, "withdraw: not good");
require(user.amount >= _amount, "withdraw: not good");
updatePool(_pid);
updatePool(_pid);
Copier
Copié
Copier
Copié
uint256 _pending = user.amount.mul(pool.acc
T
SharePerShare).div(1e18).sub(user.rewardDebt);
uint256 _pending = user.amount.mul(pool.acc
B
SharePerShare).div(1e18).sub(user.rewardDebt);
if (_pending > 0) {
if (_pending > 0) {
Copier
Copié
Copier
Copié
safe
T
ShareTransfer(_sender, _pending);
safe
B
ShareTransfer(_sender, _pending);
emit RewardPaid(_sender, _pending);
emit RewardPaid(_sender, _pending);
}
}
if (_amount > 0) {
if (_amount > 0) {
user.amount = user.amount.sub(_amount);
user.amount = user.amount.sub(_amount);
pool.token.safeTransfer(_sender, _amount);
pool.token.safeTransfer(_sender, _amount);
}
}
Copier
Copié
Copier
Copié
user.rewardDebt = user.amount.mul(pool.acc
T
SharePerShare).div(1e18);
user.rewardDebt = user.amount.mul(pool.acc
B
SharePerShare).div(1e18);
emit Withdraw(_sender, _pid, _amount);
emit Withdraw(_sender, _pid, _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];
uint256 _amount = user.amount;
uint256 _amount = user.amount;
user.amount = 0;
user.amount = 0;
user.rewardDebt = 0;
user.rewardDebt = 0;
pool.token.safeTransfer(msg.sender, _amount);
pool.token.safeTransfer(msg.sender, _amount);
emit EmergencyWithdraw(msg.sender, _pid, _amount);
emit EmergencyWithdraw(msg.sender, _pid, _amount);
}
}
Copier
Copié
Copier
Copié
// Safe
t
share transfer function, just in case if rounding error causes pool to not have enough
t
SHAREs.
// Safe
b
share transfer function, just in case if rounding error causes pool to not have enough
b
SHAREs.
function safe
T
ShareTransfer(address _to, uint256 _amount) internal {
function safe
B
ShareTransfer(address _to, uint256 _amount) internal {
uint256 _
t
shareBal =
t
share.balanceOf(address(this));
uint256 _
b
shareBal =
b
share.balanceOf(address(this));
if (_
t
shareBal > 0) {
if (_
b
shareBal > 0) {
if (_amount > _
t
shareBal) {
if (_amount > _
b
shareBal) {
t
share.safeTransfer(_to, _
t
shareBal);
b
share.safeTransfer(_to, _
b
shareBal);
} else {
} else {
Copier
Copié
Copier
Copié
t
share.safeTransfer(_to, _amount);
b
share.safeTransfer(_to, _amount);
}
}
}
}
}
}
function setOperator(address _operator) external onlyOperator {
function setOperator(address _operator) external onlyOperator {
operator = _operator;
operator = _operator;
}
}
function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external onlyOperator {
function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external onlyOperator {
if (block.timestamp < poolEndTime + 90 days) {
if (block.timestamp < poolEndTime + 90 days) {
// do not allow to drain core token (tSHARE or lps) if less than 90 days after pool ends
// do not allow to drain core token (tSHARE or lps) if less than 90 days after pool ends
Copier
Copié
Copier
Copié
require(_token !=
t
share, "
t
share");
require(_token !=
b
share, "
b
share");
uint256 length = poolInfo.length;
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
for (uint256 pid = 0; pid < length; ++pid) {
PoolInfo storage pool = poolInfo[pid];
PoolInfo storage pool = poolInfo[pid];
require(_token != pool.token, "pool.token");
require(_token != pool.token, "pool.token");
}
}
}
}
_token.safeTransfer(to, amount);
_token.safeTransfer(to, amount);
}
}
}
}
Différences enregistrées
Texte d'origine
Ouvrir un fichier
// 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/math/SafeMath.sol"; // Note that this pool has no minter key of tSHARE (rewards). // Instead, the governance will call tSHARE distributeReward method and send reward to this pool at the beginning. contract TShareRewardPool { using SafeMath for uint256; using SafeERC20 for IERC20; // governance address public operator; // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. } // Info of each pool. struct PoolInfo { IERC20 token; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. tSHAREs to distribute per block. uint256 lastRewardTime; // Last time that tSHAREs distribution occurs. uint256 accTSharePerShare; // Accumulated tSHAREs per share, times 1e18. See below. bool isStarted; // if lastRewardTime has passed } IERC20 public tshare; // 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 time when tSHARE mining starts. uint256 public poolStartTime; // The time when tSHARE mining ends. uint256 public poolEndTime; uint256 public tSharePerSecond = 0.00186122 ether; // 59500 tshare / (370 days * 24h * 60min * 60s) uint256 public runningTime = 370 days; // 370 days uint256 public constant TOTAL_REWARDS = 59500 ether; 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); event RewardPaid(address indexed user, uint256 amount); constructor( address _tshare, uint256 _poolStartTime ) public { require(block.timestamp < _poolStartTime, "late"); if (_tshare != address(0)) tshare = IERC20(_tshare); poolStartTime = _poolStartTime; poolEndTime = poolStartTime + runningTime; operator = msg.sender; } modifier onlyOperator() { require(operator == msg.sender, "TShareRewardPool: caller is not the operator"); _; } function checkPoolDuplicate(IERC20 _token) internal view { uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { require(poolInfo[pid].token != _token, "TShareRewardPool: existing pool?"); } } // Add a new lp to the pool. Can only be called by the owner. function add( uint256 _allocPoint, IERC20 _token, bool _withUpdate, uint256 _lastRewardTime ) public onlyOperator { checkPoolDuplicate(_token); if (_withUpdate) { massUpdatePools(); } if (block.timestamp < poolStartTime) { // chef is sleeping if (_lastRewardTime == 0) { _lastRewardTime = poolStartTime; } else { if (_lastRewardTime < poolStartTime) { _lastRewardTime = poolStartTime; } } } else { // chef is cooking if (_lastRewardTime == 0 || _lastRewardTime < block.timestamp) { _lastRewardTime = block.timestamp; } } bool _isStarted = (_lastRewardTime <= poolStartTime) || (_lastRewardTime <= block.timestamp); poolInfo.push(PoolInfo({ token : _token, allocPoint : _allocPoint, lastRewardTime : _lastRewardTime, accTSharePerShare : 0, isStarted : _isStarted })); if (_isStarted) { totalAllocPoint = totalAllocPoint.add(_allocPoint); } } // Update the given pool's tSHARE allocation point. Can only be called by the owner. function set(uint256 _pid, uint256 _allocPoint) public onlyOperator { massUpdatePools(); PoolInfo storage pool = poolInfo[_pid]; if (pool.isStarted) { totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add( _allocPoint ); } pool.allocPoint = _allocPoint; } // Return accumulate rewards over the given _from to _to block. function getGeneratedReward(uint256 _fromTime, uint256 _toTime) public view returns (uint256) { if (_fromTime >= _toTime) return 0; if (_toTime >= poolEndTime) { if (_fromTime >= poolEndTime) return 0; if (_fromTime <= poolStartTime) return poolEndTime.sub(poolStartTime).mul(tSharePerSecond); return poolEndTime.sub(_fromTime).mul(tSharePerSecond); } else { if (_toTime <= poolStartTime) return 0; if (_fromTime <= poolStartTime) return _toTime.sub(poolStartTime).mul(tSharePerSecond); return _toTime.sub(_fromTime).mul(tSharePerSecond); } } // View function to see pending tSHAREs on frontend. function pendingShare(uint256 _pid, address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 accTSharePerShare = pool.accTSharePerShare; uint256 tokenSupply = pool.token.balanceOf(address(this)); if (block.timestamp > pool.lastRewardTime && tokenSupply != 0) { uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp); uint256 _tshareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint); accTSharePerShare = accTSharePerShare.add(_tshareReward.mul(1e18).div(tokenSupply)); } return user.amount.mul(accTSharePerShare).div(1e18).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 tokenSupply = pool.token.balanceOf(address(this)); if (tokenSupply == 0) { pool.lastRewardTime = block.timestamp; return; } if (!pool.isStarted) { pool.isStarted = true; totalAllocPoint = totalAllocPoint.add(pool.allocPoint); } if (totalAllocPoint > 0) { uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp); uint256 _tshareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint); pool.accTSharePerShare = pool.accTSharePerShare.add(_tshareReward.mul(1e18).div(tokenSupply)); } pool.lastRewardTime = block.timestamp; } // Deposit LP tokens. function deposit(uint256 _pid, uint256 _amount) public { address _sender = msg.sender; PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_sender]; updatePool(_pid); if (user.amount > 0) { uint256 _pending = user.amount.mul(pool.accTSharePerShare).div(1e18).sub(user.rewardDebt); if (_pending > 0) { safeTShareTransfer(_sender, _pending); emit RewardPaid(_sender, _pending); } } if (_amount > 0) { pool.token.safeTransferFrom(_sender, address(this), _amount); user.amount = user.amount.add(_amount); } user.rewardDebt = user.amount.mul(pool.accTSharePerShare).div(1e18); emit Deposit(_sender, _pid, _amount); } // Withdraw LP tokens. function withdraw(uint256 _pid, uint256 _amount) public { address _sender = msg.sender; PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(_pid); uint256 _pending = user.amount.mul(pool.accTSharePerShare).div(1e18).sub(user.rewardDebt); if (_pending > 0) { safeTShareTransfer(_sender, _pending); emit RewardPaid(_sender, _pending); } if (_amount > 0) { user.amount = user.amount.sub(_amount); pool.token.safeTransfer(_sender, _amount); } user.rewardDebt = user.amount.mul(pool.accTSharePerShare).div(1e18); emit Withdraw(_sender, _pid, _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]; uint256 _amount = user.amount; user.amount = 0; user.rewardDebt = 0; pool.token.safeTransfer(msg.sender, _amount); emit EmergencyWithdraw(msg.sender, _pid, _amount); } // Safe tshare transfer function, just in case if rounding error causes pool to not have enough tSHAREs. function safeTShareTransfer(address _to, uint256 _amount) internal { uint256 _tshareBal = tshare.balanceOf(address(this)); if (_tshareBal > 0) { if (_amount > _tshareBal) { tshare.safeTransfer(_to, _tshareBal); } else { tshare.safeTransfer(_to, _amount); } } } function setOperator(address _operator) external onlyOperator { operator = _operator; } function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external onlyOperator { if (block.timestamp < poolEndTime + 90 days) { // do not allow to drain core token (tSHARE or lps) if less than 90 days after pool ends require(_token != tshare, "tshare"); uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { PoolInfo storage pool = poolInfo[pid]; require(_token != pool.token, "pool.token"); } } _token.safeTransfer(to, amount); } }
Texte modifié
Ouvrir un fichier
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; // Note that this pool has no minter key of bSHARE (rewards). // Instead, the governance will call bSHARE distributeReward method and send reward to this pool at the beginning. contract BShareRewardPool { using SafeMath for uint256; using SafeERC20 for IERC20; // governance address public operator; // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. } // Info of each pool. struct PoolInfo { IERC20 token; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. bSHAREs to distribute per block. uint256 lastRewardTime; // Last time that bSHAREs distribution occurs. uint256 accBSharePerShare; // Accumulated bSHAREs per share, times 1e18. See below. bool isStarted; // if lastRewardTime has passed } IERC20 public bshare; // 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 time when bSHARE mining starts. uint256 public poolStartTime; // The time when bSHARE mining ends. uint256 public poolEndTime; address public daoFundAddress; uint256 public bSharePerSecond = 0.003486 ether; // 50000 bshare / (166 days * 24h * 60min * 60s) uint256 public runningTime = 166 days; // 166 days uint256 public constant TOTAL_REWARDS = 50000 ether; 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); event RewardPaid(address indexed user, uint256 amount); constructor( address _bshare, address _daoFund, uint256 _poolStartTime ) { require(block.timestamp < _poolStartTime, "pool cant be started in the past"); if (_bshare != address(0)) bshare = IERC20(_bshare); if(_daoFund != address(0)) daoFundAddress = _daoFund; poolStartTime = _poolStartTime; poolEndTime = poolStartTime + runningTime; operator = msg.sender; } modifier onlyOperator() { require(operator == msg.sender, "BShareRewardPool: caller is not the operator"); _; } function checkPoolDuplicate(IERC20 _token) internal view { uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { require(poolInfo[pid].token != _token, "BShareRewardPool: existing pool?"); } } // Add new lp to the pool. Can only be called by operator. function add( uint256 _allocPoint, IERC20 _token, bool _withUpdate, uint256 _lastRewardTime ) public onlyOperator { checkPoolDuplicate(_token); if (_withUpdate) { massUpdatePools(); } if (block.timestamp < poolStartTime) { // chef is sleeping if (_lastRewardTime == 0) { _lastRewardTime = poolStartTime; } else { if (_lastRewardTime < poolStartTime) { _lastRewardTime = poolStartTime; } } } else { // chef is cooking if (_lastRewardTime == 0 || _lastRewardTime < block.timestamp) { _lastRewardTime = block.timestamp; } } bool _isStarted = (_lastRewardTime <= poolStartTime) || (_lastRewardTime <= block.timestamp); poolInfo.push(PoolInfo({ token: _token, allocPoint: _allocPoint, lastRewardTime: _lastRewardTime, accBSharePerShare: 0, isStarted: _isStarted })); if (_isStarted) { totalAllocPoint = totalAllocPoint.add(_allocPoint); } } // starting allocations for our pools // BASED-TOMB LP: 21500 $BSHARE // BSHARE-TOMB LP: 21000 $BSHARE // TEAM: 4500 $BSHARE // CURVE STABLES LP (OR GEIST STABLES LP): 3000 $BSHARE // Update the given pool's bSHARE allocation point. Can only be called by the operator. // @allocPoints for TEAM can NOT be altered after added - PID 2 // @allocPoints for main LP pools can NOT be smaller than 12,000 function set(uint256 _pid, uint256 _allocPoint) public onlyOperator { massUpdatePools(); require (_pid != 2, "CAN NOT ADJUST TEAM ALLOCATIONS"); PoolInfo storage pool = poolInfo[_pid]; if (_pid == 0 || _pid == 1) { require(_allocPoint >= 12000 * 10**18, "out of range"); // >= allocations for lp pools cant be less than 12,000 if (pool.isStarted) { totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add(_allocPoint); } } else if (_pid > 2) { if (pool.isStarted) { totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add(_allocPoint); } } pool.allocPoint = _allocPoint; } // Return accumulate rewards over the given _from to _to block. function getGeneratedReward(uint256 _fromTime, uint256 _toTime) public view returns (uint256) { if (_fromTime >= _toTime) return 0; if (_toTime >= poolEndTime) { if (_fromTime >= poolEndTime) return 0; if (_fromTime <= poolStartTime) return poolEndTime.sub(poolStartTime).mul(bSharePerSecond); return poolEndTime.sub(_fromTime).mul(bSharePerSecond); } else { if (_toTime <= poolStartTime) return 0; if (_fromTime <= poolStartTime) return _toTime.sub(poolStartTime).mul(bSharePerSecond); return _toTime.sub(_fromTime).mul(bSharePerSecond); } } // View function to see pending bSHAREs on frontend. function pendingShare(uint256 _pid, address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 accBSharePerShare = pool.accBSharePerShare; uint256 tokenSupply = pool.token.balanceOf(address(this)); if (block.timestamp > pool.lastRewardTime && tokenSupply != 0) { uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp); uint256 _bshareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint); accBSharePerShare = accBSharePerShare.add(_bshareReward.mul(1e18).div(tokenSupply)); } return user.amount.mul(accBSharePerShare).div(1e18).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 tokenSupply = pool.token.balanceOf(address(this)); if (tokenSupply == 0) { pool.lastRewardTime = block.timestamp; return; } if (!pool.isStarted) { pool.isStarted = true; totalAllocPoint = totalAllocPoint.add(pool.allocPoint); } if (totalAllocPoint > 0) { uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp); uint256 _bshareReward = _generatedReward.mul(pool.allocPoint).div(totalAllocPoint); pool.accBSharePerShare = pool.accBSharePerShare.add(_bshareReward.mul(1e18).div(tokenSupply)); } pool.lastRewardTime = block.timestamp; } // Deposit LP tokens. function deposit(uint256 _pid, uint256 _amount) public { address _sender = msg.sender; PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_sender]; updatePool(_pid); if (user.amount > 0) { uint256 _pending = user.amount.mul(pool.accBSharePerShare).div(1e18).sub(user.rewardDebt); if (_pending > 0) { safeBShareTransfer(_sender, _pending); emit RewardPaid(_sender, _pending); } } if (_amount > 0 && _pid > 2) { pool.token.safeTransferFrom(_sender, address(this), _amount); uint256 depositDebt = _amount.mul(20).div(10000); user.amount = user.amount.add(_amount.sub(depositDebt)); pool.token.safeTransfer(daoFundAddress, depositDebt); } else if (_amount > 0 && _pid <= 2) { pool.token.safeTransferFrom(_sender, address(this), _amount); user.amount = user.amount.add(_amount); } user.rewardDebt = user.amount.mul(pool.accBSharePerShare).div(1e18); emit Deposit(_sender, _pid, _amount); } // Withdraw LP tokens. function withdraw(uint256 _pid, uint256 _amount) public { address _sender = msg.sender; PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(_pid); uint256 _pending = user.amount.mul(pool.accBSharePerShare).div(1e18).sub(user.rewardDebt); if (_pending > 0) { safeBShareTransfer(_sender, _pending); emit RewardPaid(_sender, _pending); } if (_amount > 0) { user.amount = user.amount.sub(_amount); pool.token.safeTransfer(_sender, _amount); } user.rewardDebt = user.amount.mul(pool.accBSharePerShare).div(1e18); emit Withdraw(_sender, _pid, _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]; uint256 _amount = user.amount; user.amount = 0; user.rewardDebt = 0; pool.token.safeTransfer(msg.sender, _amount); emit EmergencyWithdraw(msg.sender, _pid, _amount); } // Safe bshare transfer function, just in case if rounding error causes pool to not have enough bSHAREs. function safeBShareTransfer(address _to, uint256 _amount) internal { uint256 _bshareBal = bshare.balanceOf(address(this)); if (_bshareBal > 0) { if (_amount > _bshareBal) { bshare.safeTransfer(_to, _bshareBal); } else { bshare.safeTransfer(_to, _amount); } } } function setOperator(address _operator) external onlyOperator { operator = _operator; } function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external onlyOperator { if (block.timestamp < poolEndTime + 90 days) { // do not allow to drain core token (tSHARE or lps) if less than 90 days after pool ends require(_token != bshare, "bshare"); uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { PoolInfo storage pool = poolInfo[pid]; require(_token != pool.token, "pool.token"); } } _token.safeTransfer(to, amount); } }
Trouver la différence