编译器
0.6.12+commit.27d51765
文件 1 的 8:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 8:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 8:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
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);
}
文件 4 的 8:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 5 的 8:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 6 的 8:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 7 的 8:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 8 的 8:Staker.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
contract Staker is Ownable, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
string public name;
IERC20 public token;
uint256 public totalTokenDeposited;
bool public canAlterDevelopers;
address[] public developerAddresses;
mapping (address => uint256) public developerShares;
bool public canAlterTokenEmissionSchedule;
bool public canAlterPointEmissionSchedule;
struct EmissionPoint {
uint256 blockNumber;
uint256 rate;
}
uint256 public tokenEmissionBlockCount;
mapping (uint256 => EmissionPoint) public tokenEmissionBlocks;
uint256 public pointEmissionBlockCount;
mapping (uint256 => EmissionPoint) public pointEmissionBlocks;
uint256 MAX_INT = 2**256 - 1;
uint256 internal earliestTokenEmissionBlock;
uint256 internal earliestPointEmissionBlock;
struct PoolInfo {
IERC20 token;
uint256 tokenStrength;
uint256 tokensPerShare;
uint256 pointStrength;
uint256 pointsPerShare;
uint256 lastRewardBlock;
}
IERC20[] public poolTokens;
mapping (IERC20 => PoolInfo) public poolInfo;
struct UserInfo {
uint256 amount;
uint256 tokenPaid;
uint256 pointPaid;
}
mapping (IERC20 => mapping (address => UserInfo)) public userInfo;
uint256 public totalTokenStrength;
uint256 public totalPointStrength;
uint256 public totalTokenDisbursed;
mapping (address => uint256) public userPoints;
mapping (address => uint256) public userSpentPoints;
mapping (address => bool) public approvedPointSpenders;
event Deposit(address indexed user, IERC20 indexed token, uint256 amount);
event Withdraw(address indexed user, IERC20 indexed token, uint256 amount);
event SpentPoints(address indexed source, address indexed user, uint256 amount);
constructor(string memory _name, IERC20 _token) public {
name = _name;
token = _token;
token.approve(address(this), MAX_INT);
canAlterDevelopers = true;
canAlterTokenEmissionSchedule = true;
earliestTokenEmissionBlock = MAX_INT;
canAlterPointEmissionSchedule = true;
earliestPointEmissionBlock = MAX_INT;
}
function addDeveloper(address _developerAddress, uint256 _share) external onlyOwner {
require(canAlterDevelopers,
"This Staker has locked the addition of developers; no more may be added.");
developerAddresses.push(_developerAddress);
developerShares[_developerAddress] = _share;
}
function lockDevelopers() external onlyOwner {
canAlterDevelopers = false;
}
function updateDeveloper(address _newDeveloperAddress, uint256 _newShare) external {
uint256 developerShare = developerShares[msg.sender];
require(developerShare > 0,
"You are not a developer of this Staker.");
require(_newShare <= developerShare,
"You cannot increase your developer share.");
developerShares[msg.sender] = 0;
developerAddresses.push(_newDeveloperAddress);
developerShares[_newDeveloperAddress] = _newShare;
}
function setEmissions(EmissionPoint[] memory _tokenSchedule, EmissionPoint[] memory _pointSchedule) external onlyOwner {
if (_tokenSchedule.length > 0) {
require(canAlterTokenEmissionSchedule,
"This Staker has locked the alteration of token emissions.");
tokenEmissionBlockCount = _tokenSchedule.length;
for (uint256 i = 0; i < tokenEmissionBlockCount; i++) {
tokenEmissionBlocks[i] = _tokenSchedule[i];
if (earliestTokenEmissionBlock > _tokenSchedule[i].blockNumber) {
earliestTokenEmissionBlock = _tokenSchedule[i].blockNumber;
}
}
}
require(tokenEmissionBlockCount > 0,
"You must set the token emission schedule.");
if (_pointSchedule.length > 0) {
require(canAlterPointEmissionSchedule,
"This Staker has locked the alteration of point emissions.");
pointEmissionBlockCount = _pointSchedule.length;
for (uint256 i = 0; i < pointEmissionBlockCount; i++) {
pointEmissionBlocks[i] = _pointSchedule[i];
if (earliestPointEmissionBlock > _pointSchedule[i].blockNumber) {
earliestPointEmissionBlock = _pointSchedule[i].blockNumber;
}
}
}
require(tokenEmissionBlockCount > 0,
"You must set the point emission schedule.");
}
function lockTokenEmissions() external onlyOwner {
canAlterTokenEmissionSchedule = false;
}
function lockPointEmissions() external onlyOwner {
canAlterPointEmissionSchedule = false;
}
function getDeveloperCount() external view returns (uint256) {
return developerAddresses.length;
}
function getPoolCount() external view returns (uint256) {
return poolTokens.length;
}
function getRemainingToken() external view returns (uint256) {
return token.balanceOf(address(this));
}
function addPool(IERC20 _token, uint256 _tokenStrength, uint256 _pointStrength) external onlyOwner {
require(tokenEmissionBlockCount > 0 && pointEmissionBlockCount > 0,
"Staking pools cannot be addded until an emission schedule has been defined.");
uint256 lastTokenRewardBlock = block.number > earliestTokenEmissionBlock ? block.number : earliestTokenEmissionBlock;
uint256 lastPointRewardBlock = block.number > earliestPointEmissionBlock ? block.number : earliestPointEmissionBlock;
uint256 lastRewardBlock = lastTokenRewardBlock > lastPointRewardBlock ? lastTokenRewardBlock : lastPointRewardBlock;
if (address(poolInfo[_token].token) == address(0)) {
poolTokens.push(_token);
totalTokenStrength = totalTokenStrength.add(_tokenStrength);
totalPointStrength = totalPointStrength.add(_pointStrength);
poolInfo[_token] = PoolInfo({
token: _token,
tokenStrength: _tokenStrength,
tokensPerShare: 0,
pointStrength: _pointStrength,
pointsPerShare: 0,
lastRewardBlock: lastRewardBlock
});
} else {
totalTokenStrength = totalTokenStrength.sub(poolInfo[_token].tokenStrength).add(_tokenStrength);
poolInfo[_token].tokenStrength = _tokenStrength;
totalPointStrength = totalPointStrength.sub(poolInfo[_token].pointStrength).add(_pointStrength);
poolInfo[_token].pointStrength = _pointStrength;
}
}
function getTotalEmittedTokens(uint256 _fromBlock, uint256 _toBlock) public view returns (uint256) {
require(_toBlock >= _fromBlock,
"Tokens cannot be emitted from a higher block to a lower block.");
uint256 totalEmittedTokens = 0;
uint256 workingRate = 0;
uint256 workingBlock = _fromBlock;
for (uint256 i = 0; i < tokenEmissionBlockCount; ++i) {
uint256 emissionBlock = tokenEmissionBlocks[i].blockNumber;
uint256 emissionRate = tokenEmissionBlocks[i].rate;
if (_toBlock < emissionBlock) {
totalEmittedTokens = totalEmittedTokens.add(_toBlock.sub(workingBlock).mul(workingRate));
return totalEmittedTokens;
} else if (workingBlock < emissionBlock) {
totalEmittedTokens = totalEmittedTokens.add(emissionBlock.sub(workingBlock).mul(workingRate));
workingBlock = emissionBlock;
}
workingRate = emissionRate;
}
if (workingBlock < _toBlock) {
totalEmittedTokens = totalEmittedTokens.add(_toBlock.sub(workingBlock).mul(workingRate));
}
return totalEmittedTokens;
}
function getTotalEmittedPoints(uint256 _fromBlock, uint256 _toBlock) public view returns (uint256) {
require(_toBlock >= _fromBlock,
"Points cannot be emitted from a higher block to a lower block.");
uint256 totalEmittedPoints = 0;
uint256 workingRate = 0;
uint256 workingBlock = _fromBlock;
for (uint256 i = 0; i < pointEmissionBlockCount; ++i) {
uint256 emissionBlock = pointEmissionBlocks[i].blockNumber;
uint256 emissionRate = pointEmissionBlocks[i].rate;
if (_toBlock < emissionBlock) {
totalEmittedPoints = totalEmittedPoints.add(_toBlock.sub(workingBlock).mul(workingRate));
return totalEmittedPoints;
} else if (workingBlock < emissionBlock) {
totalEmittedPoints = totalEmittedPoints.add(emissionBlock.sub(workingBlock).mul(workingRate));
workingBlock = emissionBlock;
}
workingRate = emissionRate;
}
if (workingBlock < _toBlock) {
totalEmittedPoints = totalEmittedPoints.add(_toBlock.sub(workingBlock).mul(workingRate));
}
return totalEmittedPoints;
}
function updatePool(IERC20 _token) internal {
PoolInfo storage pool = poolInfo[_token];
if (block.number <= pool.lastRewardBlock) {
return;
}
uint256 poolTokenSupply = pool.token.balanceOf(address(this));
if (address(_token) == address(token)) {
poolTokenSupply = totalTokenDeposited;
}
if (poolTokenSupply <= 0) {
pool.lastRewardBlock = block.number;
return;
}
uint256 totalEmittedTokens = getTotalEmittedTokens(pool.lastRewardBlock, block.number);
uint256 tokensReward = totalEmittedTokens.mul(pool.tokenStrength).div(totalTokenStrength).mul(1e12);
uint256 totalEmittedPoints = getTotalEmittedPoints(pool.lastRewardBlock, block.number);
uint256 pointsReward = totalEmittedPoints.mul(pool.pointStrength).div(totalPointStrength).mul(1e30);
for (uint256 i = 0; i < developerAddresses.length; ++i) {
address developer = developerAddresses[i];
uint256 share = developerShares[developer];
uint256 devTokens = tokensReward.mul(share).div(100000);
tokensReward = tokensReward - devTokens;
uint256 devPoints = pointsReward.mul(share).div(100000);
pointsReward = pointsReward - devPoints;
token.safeTransferFrom(address(this), developer, devTokens.div(1e12));
userPoints[developer] = userPoints[developer].add(devPoints.div(1e30));
}
pool.tokensPerShare = pool.tokensPerShare.add(tokensReward.div(poolTokenSupply));
pool.pointsPerShare = pool.pointsPerShare.add(pointsReward.div(poolTokenSupply));
pool.lastRewardBlock = block.number;
}
function getPendingTokens(IERC20 _token, address _user) public view returns (uint256) {
PoolInfo storage pool = poolInfo[_token];
UserInfo storage user = userInfo[_token][_user];
uint256 tokensPerShare = pool.tokensPerShare;
uint256 poolTokenSupply = pool.token.balanceOf(address(this));
if (address(_token) == address(token)) {
poolTokenSupply = totalTokenDeposited;
}
if (block.number > pool.lastRewardBlock && poolTokenSupply > 0) {
uint256 totalEmittedTokens = getTotalEmittedTokens(pool.lastRewardBlock, block.number);
uint256 tokensReward = totalEmittedTokens.mul(pool.tokenStrength).div(totalTokenStrength).mul(1e12);
tokensPerShare = tokensPerShare.add(tokensReward.div(poolTokenSupply));
}
return user.amount.mul(tokensPerShare).div(1e12).sub(user.tokenPaid);
}
function getPendingPoints(IERC20 _token, address _user) public view returns (uint256) {
PoolInfo storage pool = poolInfo[_token];
UserInfo storage user = userInfo[_token][_user];
uint256 pointsPerShare = pool.pointsPerShare;
uint256 poolTokenSupply = pool.token.balanceOf(address(this));
if (address(_token) == address(token)) {
poolTokenSupply = totalTokenDeposited;
}
if (block.number > pool.lastRewardBlock && poolTokenSupply > 0) {
uint256 totalEmittedPoints = getTotalEmittedPoints(pool.lastRewardBlock, block.number);
uint256 pointsReward = totalEmittedPoints.mul(pool.pointStrength).div(totalPointStrength).mul(1e30);
pointsPerShare = pointsPerShare.add(pointsReward.div(poolTokenSupply));
}
return user.amount.mul(pointsPerShare).div(1e30).sub(user.pointPaid);
}
function getAvailablePoints(address _user) public view returns (uint256) {
uint256 concreteTotal = userPoints[_user];
uint256 pendingTotal = 0;
for (uint256 i = 0; i < poolTokens.length; ++i) {
IERC20 poolToken = poolTokens[i];
uint256 _pendingPoints = getPendingPoints(poolToken, _user);
pendingTotal = pendingTotal.add(_pendingPoints);
}
uint256 spentTotal = userSpentPoints[_user];
return concreteTotal.add(pendingTotal).sub(spentTotal);
}
function getTotalPoints(address _user) external view returns (uint256) {
uint256 concreteTotal = userPoints[_user];
uint256 pendingTotal = 0;
for (uint256 i = 0; i < poolTokens.length; ++i) {
IERC20 poolToken = poolTokens[i];
uint256 _pendingPoints = getPendingPoints(poolToken, _user);
pendingTotal = pendingTotal.add(_pendingPoints);
}
return concreteTotal.add(pendingTotal);
}
function getSpentPoints(address _user) external view returns (uint256) {
return userSpentPoints[_user];
}
function deposit(IERC20 _token, uint256 _amount) external nonReentrant {
PoolInfo storage pool = poolInfo[_token];
require(pool.tokenStrength > 0 || pool.pointStrength > 0,
"You cannot deposit assets into an inactive pool.");
UserInfo storage user = userInfo[_token][msg.sender];
updatePool(_token);
if (user.amount > 0) {
uint256 pendingTokens = user.amount.mul(pool.tokensPerShare).div(1e12).sub(user.tokenPaid);
token.safeTransferFrom(address(this), msg.sender, pendingTokens);
totalTokenDisbursed = totalTokenDisbursed.add(pendingTokens);
uint256 pendingPoints = user.amount.mul(pool.pointsPerShare).div(1e30).sub(user.pointPaid);
userPoints[msg.sender] = userPoints[msg.sender].add(pendingPoints);
}
pool.token.safeTransferFrom(address(msg.sender), address(this), _amount);
if (address(_token) == address(token)) {
totalTokenDeposited = totalTokenDeposited.add(_amount);
}
user.amount = user.amount.add(_amount);
user.tokenPaid = user.amount.mul(pool.tokensPerShare).div(1e12);
user.pointPaid = user.amount.mul(pool.pointsPerShare).div(1e30);
emit Deposit(msg.sender, _token, _amount);
}
function withdraw(IERC20 _token, uint256 _amount) external nonReentrant {
PoolInfo storage pool = poolInfo[_token];
UserInfo storage user = userInfo[_token][msg.sender];
require(user.amount >= _amount,
"You cannot withdraw that much of the specified token; you are not owed it.");
updatePool(_token);
uint256 pendingTokens = user.amount.mul(pool.tokensPerShare).div(1e12).sub(user.tokenPaid);
token.safeTransferFrom(address(this), msg.sender, pendingTokens);
totalTokenDisbursed = totalTokenDisbursed.add(pendingTokens);
uint256 pendingPoints = user.amount.mul(pool.pointsPerShare).div(1e30).sub(user.pointPaid);
userPoints[msg.sender] = userPoints[msg.sender].add(pendingPoints);
if (address(_token) == address(token)) {
totalTokenDeposited = totalTokenDeposited.sub(_amount);
}
user.amount = user.amount.sub(_amount);
user.tokenPaid = user.amount.mul(pool.tokensPerShare).div(1e12);
user.pointPaid = user.amount.mul(pool.pointsPerShare).div(1e30);
pool.token.safeTransfer(address(msg.sender), _amount);
emit Withdraw(msg.sender, _token, _amount);
}
function approvePointSpender(address _spender, bool _approval) external onlyOwner {
approvedPointSpenders[_spender] = _approval;
}
function spendPoints(address _user, uint256 _amount) external {
require(approvedPointSpenders[msg.sender],
"You are not permitted to spend user points.");
uint256 _userPoints = getAvailablePoints(_user);
require(_userPoints >= _amount,
"The user does not have enough points to spend the requested amount.");
userSpentPoints[_user] = userSpentPoints[_user].add(_amount);
emit SpentPoints(msg.sender, _user, _amount);
}
function sweep(IERC20 _token) external onlyOwner {
uint256 balance = _token.balanceOf(address(this));
_token.safeTransferFrom(address(this), msg.sender, balance);
}
}
{
"compilationTarget": {
"contracts/Staker.sol": "Staker"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"contract IERC20","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SpentPoints","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_developerAddress","type":"address"},{"internalType":"uint256","name":"_share","type":"uint256"}],"name":"addDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenStrength","type":"uint256"},{"internalType":"uint256","name":"_pointStrength","type":"uint256"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"bool","name":"_approval","type":"bool"}],"name":"approvePointSpender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedPointSpenders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canAlterDevelopers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canAlterPointEmissionSchedule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canAlterTokenEmissionSchedule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"developerAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"developerShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getAvailablePoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeveloperCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getPendingPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getPendingTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRemainingToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getSpentPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromBlock","type":"uint256"},{"internalType":"uint256","name":"_toBlock","type":"uint256"}],"name":"getTotalEmittedPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromBlock","type":"uint256"},{"internalType":"uint256","name":"_toBlock","type":"uint256"}],"name":"getTotalEmittedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getTotalPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDevelopers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockPointEmissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockTokenEmissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pointEmissionBlockCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pointEmissionBlocks","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"tokenStrength","type":"uint256"},{"internalType":"uint256","name":"tokensPerShare","type":"uint256"},{"internalType":"uint256","name":"pointStrength","type":"uint256"},{"internalType":"uint256","name":"pointsPerShare","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolTokens","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"internalType":"struct Staker.EmissionPoint[]","name":"_tokenSchedule","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"internalType":"struct Staker.EmissionPoint[]","name":"_pointSchedule","type":"tuple[]"}],"name":"setEmissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"spendPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenEmissionBlockCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenEmissionBlocks","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPointStrength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokenDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokenDisbursed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokenStrength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newDeveloperAddress","type":"address"},{"internalType":"uint256","name":"_newShare","type":"uint256"}],"name":"updateDeveloper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenPaid","type":"uint256"},{"internalType":"uint256","name":"pointPaid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userSpentPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]